/* --------------------------------------------------------------------------
   Footer
   -------------------------------------------------------------------------- */

.footer {
    margin-top: auto;
    background: var(--grape);
    color: var(--lav-200);
    padding: 1.5rem 0;
    font-size: 0.92rem;
    font-weight: 600;
}

[data-theme="dark"] .footer { color: var(--ink-soft); border-top: 3px solid var(--lav-200); }

.footer a { color: #fff; }

.footer__inner {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem 1.5rem;
    align-items: center;
    justify-content: space-between;
}

/* --------------------------------------------------------------------------
   Site tabs — About / Quiz / Game / Merchandise
   Sits in the masthead alongside the wordmark. Repeated identically (via
   data-site-tab, not ids) on every logged-in page so it always reads as one
   continuous nav rather than four different headers.
   -------------------------------------------------------------------------- */

.site-tabs {
    display: flex;
    gap: 0.3rem;
    background: var(--surface-2);
    border-radius: var(--r-pill);
    padding: 0.3rem;
    position: relative;
}

.site-tab {
    border: 0;
    background: transparent;
    border-radius: var(--r-pill);
    padding: 0.55rem 1.1rem;
    font-family: var(--display);
    font-weight: 800;
    font-size: 0.92rem;
    color: var(--ink-soft);
    cursor: pointer;
    white-space: nowrap;
    transition: background 140ms ease, color 140ms ease;
    position: relative;
    z-index: 1;
}

/* Simple, clean active state: the pill itself fills, no sliding bubble,
   no scale pop — just a quiet colour change. */
.site-tab:hover:not(.is-active) { color: var(--violet-ink); }

.site-tab.is-active {
    background: var(--violet);
    color: #fff;
}

/* Honour reduced motion. */
@media (prefers-reduced-motion: reduce) {
    .site-tab { transition: none; }
}

.site-tabs--dark { background: rgba(255, 255, 255, 0.1); }
.site-tabs--dark .site-tab { color: rgba(255, 255, 255, 0.75); }
.site-tabs--dark .site-tab:hover { color: #fff; }
.site-tabs--dark .site-tab.is-active { background: #fff; color: var(--grape); }

/* Compact masthead on phones: tighter paddings and a smaller wordmark, and
   everything in the nav cluster stays on ONE row beside the logo instead of
   wrapping underneath it. */
@media (max-width: 780px) {
    .masthead__inner { padding: 0.45rem 0; gap: 0.5rem; flex-wrap: nowrap; }
    .wordmark { gap: 0.5rem; flex: 1 1 auto; min-width: 0; }
    .wordmark__mark { width: 34px; height: 34px; border-width: 2px; border-radius: 9px; flex: none; }
    .wordmark__name { font-size: 1.1rem; }
    .wordmark__tagline { display: none; }
    .masthead__nav { flex: 0 0 auto; gap: 0.35rem; flex-wrap: nowrap; justify-content: flex-end; }
    .masthead__nav .btn { padding: 0.55rem 0.65rem; min-height: 40px; font-size: 0.9rem; }
    .masthead__nav .btn--icon { padding: 0.55rem; }
    .masthead__nav .btn--icon svg { width: 17px; height: 17px; }

    /* Log in / Log out live at the bottom of the burger drawer on small
       screens (see MOBILE_NAV_HTML). Dropping the wide masthead copy is what
       guarantees the theme, BM/EN and burger buttons fit beside the logo on
       one row instead of wrapping below it. */
    .masthead__auth-btn { display: none; }

    .crumb { gap: 0.45rem; }
    .crumb__divider { display: none; }
    .link-back { padding: 0.35rem 0.6rem; font-size: 0.85rem; }
}

@media (max-width: 780px) {
    /* The burger replaces the inline strip on small screens — a wrapped
       two-row strip in a sticky header ate too much vertical space. */
    .site-tabs { display: none; }
}

/* The tab strip's horizontal position depends on how much the wordmark and
   the button cluster around it weigh — pages with fewer masthead buttons
   (e.g. the signed-out login page) used to push the tabs off-centre compared
   to pages with a full button set. Giving both flanks equal, matching growth
   keeps the strip dead centre everywhere, no matter what sits beside it. */
@media (min-width: 781px) {
    .masthead__inner > .wordmark { flex: 1 1 0; }
    .masthead__inner > .masthead__nav { flex: 1 1 0; justify-content: flex-end; }
}

/* --------------------------------------------------------------------------
   Burger toggle + mobile drawer
   Below 780px the inline tab strip disappears and the burger takes over,
   opening a slide-down drawer under the masthead. One body-level drawer
   serves every masthead copy.
   -------------------------------------------------------------------------- */

/* Comfortable tap target on touch screens (44px is the usual minimum);
   slightly tighter on phones so the compact header stays one strip tall. */
.burger-toggle {
    width: 48px;
    height: 48px;
    padding: 0 !important;
    display: none;
    align-items: center;
    justify-content: center;
}

@media (max-width: 640px) {
    .burger-toggle { width: 40px; height: 40px; }
}

.burger-toggle svg { width: 24px; height: 24px; }

/* Burger shows the hamburger icon; the X shows only while the menu is open. */
.burger-toggle .icon-close { display: none; }
.burger-toggle[aria-expanded="true"] .icon-burger { display: none; }
.burger-toggle[aria-expanded="true"] .icon-close { display: block; }

@media (max-width: 780px) {
    .burger-toggle { display: inline-flex; }
}

/* The drawer sits at body level (not inside any page), so it can overlay the
   masthead it slides out from. The full-screen container doubles as a
   tap-catcher: a touch anywhere outside the sheet closes the menu instead
   of clicking through to the page underneath. */
.mobile-nav {
    position: fixed;
    inset: 0;
    /* Sits UNDER the sticky masthead (z 50) on purpose: the sheet drops from
       below the masthead and never overlaps it, so the burger — which turns
       into the X — stays on top and clickable while the menu is open.
       Above page overlays (z 40), below modals (z 60). */
    z-index: 45;
    /* paddingTop is set in JS from the live masthead height; this fallback
       covers the frame before the first measurement lands. */
    padding-top: 96px;
    background: rgba(13, 24, 54, 0);
    transition: background 200ms ease;
    pointer-events: auto;
}

/* While closed (or fading out) the container must never swallow clicks meant
   for the page underneath. */
.mobile-nav:not(.is-open) { pointer-events: none; }

/* A soft dim makes the rest of the page read as inert while the menu is
   open — and doubles as the visible tap-outside-to-close affordance
   (wired in navigation.js: a click on the container itself closes). */
.mobile-nav.is-open { background: rgba(13, 24, 54, 0.45); }

.mobile-nav__inner {
    background: var(--surface);
    border: 2px solid var(--lav-200);
    border-top: 0;
    border-radius: 0 0 var(--r-lg) var(--r-lg);
    box-shadow: 0 18px 40px rgba(43, 27, 84, 0.25);
    margin: 0 0.75rem;
    padding: 0.6rem;
    display: grid;
    gap: 0.35rem;
    transform: translateY(-16px);
    opacity: 0;
    transition: transform 200ms ease-out, opacity 200ms ease-out;
    pointer-events: auto;
}

.mobile-nav.is-open .mobile-nav__inner {
    transform: translateY(0);
    opacity: 1;
}

.mobile-nav__link {
    border: 0;
    background: transparent;
    border-radius: var(--r-pill);
    font-family: var(--display);
    font-weight: 800;
    font-size: 1.02rem;
    color: var(--ink-soft);
    text-align: left;
    padding: 0.85rem 1rem;
    min-height: 48px;
    display: flex;
    align-items: center;
    justify-content: space-between;
    transition: background 120ms ease, color 120ms ease;
}

.mobile-nav__link:hover { background: var(--surface-2); color: var(--violet-ink); }

.mobile-nav__link.is-active {
    background: var(--violet);
    color: #fff;
}

/* Divider above the Log in / Log out entry at the bottom of the drawer. */
.mobile-nav__divider {
    height: 2px;
    margin: 0.45rem 0.35rem 0.35rem;
    background: var(--lav-200);
    border-radius: var(--r-pill);
}

/* The auth entry sits at the very bottom of the drawer (after the divider);
   signing out gets the coral treatment, signing in stays ghost. */
.mobile-nav__link--auth { margin-top: auto; }

.mobile-nav__link--auth.is-signedin {
    color: var(--bad-d);
    justify-content: center;
}

.mobile-nav__link--auth.is-signedin:hover { background: var(--wash-coral); color: var(--bad-d); }

/* A touch of privacy on the burger menu when the site is in dark mode. */
[data-theme="dark"] .mobile-nav__inner {
    background: var(--surface);
    border-color: var(--lav-200);
}

/* --------------------------------------------------------------------------
   Centred single-panel auth pages (forgot / reset password)
   -------------------------------------------------------------------------- */

.auth-center {
    max-width: 460px;
    margin: 2rem auto 0;
    text-align: center;
}

.auth-center .panel { text-align: left; }

.link-plain {
    display: inline-block;
    background: none;
    border: 0;
    padding: 0;
    font-family: var(--body);
    font-weight: 700;
    font-size: 0.9rem;
    color: var(--violet-ink);
    cursor: pointer;
}

.link-plain:hover { text-decoration: underline; }

/* --------------------------------------------------------------------------
   Merchandise page
   The masthead, hero, buttons and footer all come from the shared components,
   so the merch page reads exactly like every other tab — the classes below
   only style the product grid, badges and perks strip.
   -------------------------------------------------------------------------- */

.merch__grid-wrap { padding: 2.5rem 0 3rem; }

.merch__grid {
    display: grid;
    gap: 1.5rem;
    grid-template-columns: repeat(2, 1fr);
}

@media (min-width: 700px)  { .merch__grid { grid-template-columns: repeat(3, 1fr); } }
@media (min-width: 1100px) { .merch__grid { grid-template-columns: repeat(4, 1fr); } }

/* One product tile. The image area is a placeholder square until real photos
   go in — swap the .merch__img-fallback markup in js/merch.js for an <img>.
   The whole card opens the product's detail modal. */
.merch__card {
    display: flex;
    flex-direction: column;
    width: 100%;
    text-align: left;
    background: var(--surface);
    border: 2px solid var(--lav-200);
    border-radius: var(--r);
    overflow: hidden;
    cursor: pointer;
    font: inherit;
    color: inherit;
    transition: transform 140ms ease, box-shadow 140ms ease, border-color 140ms ease;
}

.merch__card:hover { transform: translateY(-4px); border-color: var(--violet); box-shadow: var(--float); }
.merch__card:focus-visible { outline: 3px solid var(--violet); outline-offset: 2px; }

.merch__img {
    position: relative;
    aspect-ratio: 1 / 1;
    background: var(--surface-2);
    overflow: hidden;
}

.merch__img img { width: 100%; height: 100%; object-fit: cover; display: block; }

.merch__img-fallback {
    position: absolute;
    inset: 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 0.5rem;
    color: var(--ink-mute);
    background:
        repeating-linear-gradient(45deg, var(--lav-100) 0 10px, var(--surface-2) 10px 20px);
}

.merch__img-fallback svg { width: 34px; height: 34px; opacity: 0.6; }
.merch__img-fallback span { font-size: 0.72rem; font-weight: 700; letter-spacing: 0.04em; }

.merch__badge {
    position: absolute;
    top: 0.6rem;
    left: 0.6rem;
    font-family: var(--display);
    font-weight: 800;
    font-size: 0.68rem;
    letter-spacing: 0.05em;
    text-transform: uppercase;
    background: var(--sun);
    color: var(--grape);
    border-radius: var(--r-pill);
    padding: 0.2rem 0.55rem;
}

.merch__badge--out { background: var(--ink-mute); color: #fff; }

.merch__body { padding: 0.9rem 1rem 1.1rem; display: flex; flex-direction: column; gap: 0.3rem; flex: 1; }

.merch__name {
    font-family: var(--display);
    font-weight: 700;
    font-size: 1rem;
    line-height: 1.3;
    color: var(--heading);
}

.merch__price-row {
    display: flex;
    align-items: baseline;
    gap: 0.5rem;
    margin-top: 0.2rem;
}

.merch__price { font-family: var(--display); font-weight: 800; font-size: 1.05rem; color: var(--heading); }

/* A quiet "tap for details" hint, replacing the old add-to-cart button. */
.merch__view {
    margin-top: 0.6rem;
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    font-family: var(--display);
    font-weight: 800;
    font-size: 0.82rem;
    color: var(--violet-ink);
}

.merch__view svg { width: 15px; height: 15px; }

/* --------------------------------------------------------------------------
   Product detail
   -------------------------------------------------------------------------- */

/* The WhatsApp button in the product detail contact block. */
.merch-detail__contact .btn svg { width: 20px; height: 20px; flex: none; }

.merch__perks {
    display: grid;
    gap: 1.25rem;
    grid-template-columns: 1fr;
    padding: 2.5rem 0 3.5rem;
    border-top: 3px solid var(--lav-200);
}

@media (min-width: 720px) { .merch__perks { grid-template-columns: repeat(3, 1fr); } }

.merch__perk { display: flex; align-items: flex-start; gap: 0.85rem; }
.merch__perk svg { width: 26px; height: 26px; flex: none; color: var(--violet); margin-top: 0.1rem; }
.merch__perk strong { display: block; font-family: var(--display); font-weight: 800; color: var(--heading); }
.merch__perk span { display: block; font-size: 0.88rem; color: var(--ink-mute); }

/* Product detail: gallery on one side, description + contact on the other. */
.merch-detail {
    display: grid;
    gap: 1.5rem;
    grid-template-columns: 1fr;
}

@media (min-width: 620px) {
    .merch-detail { grid-template-columns: 1fr 1fr; align-items: start; }
}

.merch-detail__main {
    position: relative;
    aspect-ratio: 1 / 1;
    border-radius: var(--r);
    overflow: hidden;
    background: var(--surface-2);
}

.merch-detail__main img { width: 100%; height: 100%; object-fit: cover; display: block; }
.merch-detail__main .merch__img-fallback { position: absolute; }

.merch-detail__thumbs {
    display: flex;
    gap: 0.5rem;
    margin-top: 0.6rem;
    flex-wrap: wrap;
}

.merch-detail__thumb {
    width: 56px;
    height: 56px;
    border-radius: var(--r-sm);
    border: 2px solid var(--lav-200);
    background: var(--surface-2);
    overflow: hidden;
    cursor: pointer;
    padding: 0;
}

.merch-detail__thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
.merch-detail__thumb.is-active { border-color: var(--violet); }

.merch-detail__info { display: flex; flex-direction: column; gap: 0.75rem; }
.merch-detail__info .merch__price { font-size: 1.3rem; }
.merch-detail__info .prose { color: var(--ink-soft); white-space: pre-line; }

.merch-detail__contact {
    margin-top: 0.5rem;
    padding-top: 1rem;
    border-top: 3px dotted var(--lav-200);
}

/* --------------------------------------------------------------------------
   Scroll reveal — fades/slides elements in as they enter the viewport.
   The .reveal class sets the hidden starting state; JS (js/features/scroll-reveal.js,
   initScrollReveal) adds .reveal--in once an element has been observed
   crossing into view, which is what triggers the transition below.
   -------------------------------------------------------------------------- */

.reveal {
    opacity: 0;
    transform: translateY(28px);
    transition: opacity 0.6s ease, transform 0.6s ease;
}

.reveal.reveal--in { opacity: 1; transform: translateY(0); }

/* Once the entrance has played, hand transition control back to the hover
   effects (card lift, shadow, border) — otherwise the .reveal entrance
   timing would make every hover feel sluggish. JS adds .reveal-done ~700ms
   after an element surfaces. */
.reveal.reveal-done {
    transition: transform 200ms cubic-bezier(0.34, 1.56, 0.64, 1),
                box-shadow 200ms ease, border-color 200ms ease;
}

/* Optional cascade: a .stagger container deals its revealed children in one
   after another, like cards laid on a table. Used on the ecosystem grid. */
.stagger > .reveal--in:nth-child(2) { transition-delay: 70ms; }
.stagger > .reveal--in:nth-child(3) { transition-delay: 140ms; }
.stagger > .reveal--in:nth-child(4) { transition-delay: 210ms; }
.stagger > .reveal--in:nth-child(5) { transition-delay: 280ms; }

/* Respect users who've asked for less motion — show content immediately. */
@media (prefers-reduced-motion: reduce) {
    .reveal { opacity: 1; transform: none; transition: none; }
}

/* --------------------------------------------------------------------------
   About page — story, ecosystem, impact, social mission, SDG, award
   -------------------------------------------------------------------------- */

/* Long-form copy pasted with blank lines between paragraphs. Preserves those
   blank lines as paragraph breaks without needing separate <p> tags. */
.prose-pre { white-space: pre-line; }

/* "What is IlmuBridge?" — copy beside the mascot illustration; the pair stacks
   into one column on narrow screens, with the image below the text. */
.about-what {
    display: grid;
    gap: 1.5rem;
    grid-template-columns: minmax(0, 1fr);
    align-items: center;
}

@media (min-width: 920px) {
    .about-what { grid-template-columns: minmax(0, 1fr) 360px; gap: 2.5rem; }
}

.about-what__img {
    width: 100%;
    /* Overrides the height="2048" attribute: without this the box renders
       2048px tall while the width caps at 420px — a very long image. */
    height: auto;
    max-width: 420px;
    margin-inline: auto;
    /* The artwork ships with a transparent background, so it gets no card
       frame — the character sits straight on the panel. drop-shadow follows
       the silhouette rather than drawing a rectangle, so it blends while
       keeping a touch of depth. */
    filter: drop-shadow(0 12px 24px rgba(43, 27, 84, 0.16));
}

/* A big pulled-quote, used for "What if students could experience learning…" */
.about-quote {
    font-family: var(--display);
    font-weight: 700;
    font-size: clamp(1.4rem, 3vw, 1.9rem);
    line-height: 1.35;
    color: var(--heading);
    max-width: 46ch;
    margin: 0 0 2rem;
    padding-left: 1.1rem;
    border-left: 5px solid var(--violet);
}

/* A short, confident closing line, e.g. "That idea became IlmuBridge." */
.about-punch {
    font-family: var(--display);
    font-weight: 800;
    font-size: clamp(1.3rem, 2.6vw, 1.6rem);
    color: var(--violet-ink);
    margin: 2rem 0 0;
    text-align: center;
}

/* Four programme results, each with a placeholder photo + write-up. */
.impact-grid {
    display: grid;
    gap: 1.5rem;
    grid-template-columns: 1fr;
}

@media (min-width: 720px) { .impact-grid { grid-template-columns: repeat(2, 1fr); } }

.impact-card {
    background: var(--surface);
    border: 3px solid var(--lav-200);
    border-radius: var(--r-lg);
    overflow: hidden;
    box-shadow: var(--ledge);
}

.impact-card__body { padding: 1.5rem; }
.impact-card__body .subject { margin-bottom: 0.6rem; }
.impact-card__body .card__title { margin: 0 0 0.6rem; }

/* Photo strip at the top of each impact card. Two photos sit side by side,
   with the write-up below in .impact-card__body. */
.about-photo {
    aspect-ratio: 16 / 9;
    display: flex;
    flex-direction: row;
    align-items: stretch;
    justify-content: center;
    gap: 2px;
    color: var(--ink-mute);
    background: var(--surface-2);
    overflow: hidden;
}

.about-photo img {
    flex: 1 1 50%;
    width: 50%;
    height: 100%;
    object-fit: cover;
    display: block;
}

.about-photo svg { width: 34px; height: 34px; opacity: 0.6; }
.about-photo span { font-size: 0.78rem; font-weight: 700; letter-spacing: 0.02em; }

/* Big SDG number-and-label badge sitting beside the SDG write-up. */
.sdg-badge {
    background: var(--violet);
    color: #fff;
    border-radius: var(--r-lg);
    padding: 2.5rem 1.5rem;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    text-align: center;
    box-shadow: var(--ledge-lg);
    min-height: 180px;
}

.sdg-badge__num {
    font-family: var(--display);
    font-weight: 800;
    font-size: clamp(2.4rem, 6vw, 3.2rem);
    line-height: 1;
}

.sdg-badge__label {
    font-family: var(--display);
    font-weight: 700;
    font-size: 1.05rem;
    margin-top: 0.4rem;
    opacity: 0.92;
}

/* Two award photos stacked beside the achievement write-up in the hero.
   Always stacked: these are portrait photos, and a side-by-side flex row
   cannot shrink below their intrinsic width (min-width:auto), so on phones
   the second photo used to overflow past the viewport and the hero's
   overflow:hidden clipped it out of sight entirely. */
.award-photos {
    display: flex;
    flex-direction: column;
    gap: 0.75rem;
    min-width: 0;
}

.award-photos img {
    width: 100%;
    min-width: 0;
    aspect-ratio: 4 / 3;
    object-fit: cover;
    border-radius: var(--r-lg);
    box-shadow: var(--ledge-lg);
}

/* --------------------------------------------------------------------------
   Utilities
   -------------------------------------------------------------------------- */

.hidden { display: none !important; }
.mb-1 { margin-bottom: 0.5rem; }
.mb-2 { margin-bottom: 1rem; }
.mb-3 { margin-bottom: 1.6rem; }
.mb-4 { margin-bottom: 2.25rem; }
.mt-2 { margin-top: 1rem; }
.center { text-align: center; }

.sr-only {
    position: absolute;
    width: 1px; height: 1px;
    padding: 0; margin: -1px;
    overflow: hidden;
    clip: rect(0 0 0 0);
    white-space: nowrap;
    border: 0;
}

@media (prefers-reduced-motion: reduce) {
    * { transition: none !important; animation: none !important; }
    html { scroll-behavior: auto; }
}

/* ==========================================================================
   Mobile UX pass — comfort & touch-friendliness on phones
   The burger drawer lives earlier in this file (site tabs section). This
   block handles layout: single-column flows, roomier hit areas, and
   full-width sheets so dialogs never fight the viewport.
   ========================================================================== */

/* Sticky mastheads already read better slim on phones. */
@media (max-width: 640px) {
    .masthead { padding-block: 0.65rem; }

    /* Modals become edge-to-edge sheets with comfortable side margins, and
       their bodies scroll rather than the page behind them. */
    .modal {
        width: calc(100vw - 16px);
        max-width: calc(100vw - 16px);
        max-height: calc(100dvh - 16px);
        overflow-y: auto;
        margin: 8px auto;
        border-radius: var(--r-lg);
    }

    /* The helper composer shrinks so the on-screen keyboard doesn't bury it. */
    .ai__composer textarea { min-height: 0; max-height: 3.2em; }

    /* Single-column splits: the progress + leaderboard pair, the lesson +
       quiz pair, and the merch gallery no longer squeeze side by side. */
    .split { grid-template-columns: minmax(0, 1fr); }

    /* Grid-blowout guard: a 1fr track sizes to min-content by default, so one
       long unbreakable word (a name, a big score, a wide pill) can push the
       progress + leaderboard panels off-centre and clip them against the
       viewport edge. minmax(0, 1fr) lets their content shrink instead. */
    .panel,
    .record,
    .record__name,
    .record__points,
    .board__row,
    .board__name,
    .board__points,
    .tabs { min-width: 0; max-width: 100%; }
    .panel { overflow-wrap: break-word; }

    /* Centering fallback: if something inside still refuses to shrink, the
       box itself stays centred and clips evenly instead of sliding sideways. */
    #userHomePage main > .shell { width: 100%; }

    /* The award hero pair drops below each other instead of squeezing.
       minmax(0, …) per the grid-blowout guard: a bare 1fr track sizes to the
       images' min-content (their intrinsic width) and slides the panel off
       the phone screen. */
    .hero .split--even { grid-template-columns: minmax(0, 1fr); }

    /* A couple of loose desktop paddings are too generous on a phone. */
    .section { padding-block: 1.25rem; }
    .panel { padding: 1.25rem; }

    /* The floating study-helper panel becomes a near-full-width sheet above
       the bubble; 70dvh respects the on-screen keyboard. */
    .ai__panel { width: calc(100vw - 24px); max-height: 70dvh; }
}

/* iOS Safari: prevent the browser from zooming when an input gets focus
   (anything below 16px triggers it). Inputs are 16px+ already; this keeps
   selects and the helper textarea consistent too. */
@media (max-width: 640px) {
    input, select, textarea { font-size: 16px !important; }
}

/* Respect the notch/home-indicator with safe-area padding on phones. */
@supports (padding: max(0px)) {
    @media (max-width: 640px) {
        .masthead { padding-left: max(0.75rem, env(safe-area-inset-left));
                    padding-right: max(0.75rem, env(safe-area-inset-right)); }
        .shell { padding-left: max(0.9rem, env(safe-area-inset-left));
                 padding-right: max(0.9rem, env(safe-area-inset-right)); }
        .footer { padding-bottom: max(1.2rem, env(safe-area-inset-bottom)); }
    }
}
