/* =============================================================================
   🍎 APPLE COMPATIBILITY LAYER
   ---------------------------------------------------------------------------
   Loaded LAST so its rules override anything above. Addresses:
     · iPad / iPhone safe-area insets (notch, home-indicator, dynamic island)
     · iOS Safari URL-bar shift (100dvh instead of 100vh)
     · Touch tap-target minimum (44×44pt per Apple HIG)
     · iPhone-narrow layouts (≤ 480 px) — stack heavy panels vertically
     · iPad-portrait layouts (≤ 1024 px) — tighten grid columns
     · Heavy FX trimmed on small screens (oni-bi count, particle limits)
     · Font-smoothing + better serif fallback chain for kanji on iOS
     · Pointer/touch hybrid handling
     · -webkit-tap-highlight-color removal
     · Disable hover-only hauntings on touch-only devices (handled in JS;
       this file just provides the .ghost-touch-mode class hook)
   ============================================================================= */


/* ─────────────────────────────────────────────────────────────────────
   📐 SAFE AREA INSETS — respect the notch / dynamic island / home indicator
   The cockpit's outer scaffolding (nav + page-body) now lives INSIDE
   the safe area on devices that have one.
   ───────────────────────────────────────────────────────────────────── */

@supports (padding-top: env(safe-area-inset-top)) {
    body {
        padding-top:    env(safe-area-inset-top);
        padding-bottom: env(safe-area-inset-bottom);
        padding-left:   env(safe-area-inset-left);
        padding-right:  env(safe-area-inset-right);
    }
    /* Sticky nav should stay visually pinned to the safe-area edge, not
       the absolute viewport edge, so the notch doesn't overlap it.
       NOTE: this previously targeted "header.cockpit-header", which
       doesn't exist anywhere in the markup — the real element is
       <header class="hero">. That selector never matched anything. */
    .nav-bar, .cockpit-nav, header.hero {
        padding-top: env(safe-area-inset-top);
    }
}


/* ─────────────────────────────────────────────────────────────────────
   📏 FONT + RENDERING — iOS Safari likes -webkit-font-smoothing and
   antialiasing for the serif/kanji typography we're using.
   ───────────────────────────────────────────────────────────────────── */

body {
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    text-rendering: optimizeLegibility;
    /* Prevent iOS Safari from auto-scaling text on orientation change */
    -webkit-text-size-adjust: 100%;
            text-size-adjust: 100%;
    /* Remove the grey rectangle on tap */
    -webkit-tap-highlight-color: transparent;
}

/* The Yu Mincho fonts we picked exist on most Win/Mac but iOS uses
   Hiragino. Ensure the fallback is real — iOS has Hiragino Mincho ProN. */
[lang="ja"],
.glyph-icon, .ghost-watcher, .ghost-onibi, .ghost-stranger-glyph,
.ghost-kami-kanji, .ghost-mystic-kanji,
.bond-season-kanji, .room-watermark,
.gm-pc-kanji, .panel-aphorism, .panel-aphorism-mark {
    font-family: "Yu Mincho", "Hiragino Mincho ProN", "Hiragino Mincho Pro",
                 "MS Mincho", "Times New Roman", Georgia, serif;
}


/* ─────────────────────────────────────────────────────────────────────
   📐 DYNAMIC VIEWPORT HEIGHT — iOS Safari hides/shows the URL bar,
   which makes 100vh JUMP. dvh = "dynamic viewport height" tracks it.
   Provide fallbacks so older browsers still get 100vh.
   ───────────────────────────────────────────────────────────────────── */

@supports (height: 100dvh) {
    .full-height,
    .ghost-kami,
    .vault-overlay,
    .meta-ceremony,
    .tc-overlay,
    .mac-overlay {
        height: 100dvh !important;
        min-height: 100dvh !important;
    }
}


/* ─────────────────────────────────────────────────────────────────────
   👆 TAP TARGETS — Apple HIG: minimum 44×44pt
   Don't size up everything; just give the common interactive controls a
   floor on touch devices.
   ───────────────────────────────────────────────────────────────────── */

@media (hover: none) and (pointer: coarse) {
    /* Nav pills */
    .nav-pill, .arena-tab, .vault-tab,
    /* Buttons everywhere */
    button:not(.tiny-btn):not(.icon-btn),
    .btn-import, .btn-lock, .btn-fetch, .btn-check, .btn-clear,
    .panar-btn, .upload-run-btn, .upload-clear-btn,
    .filter-chip, .spirit-mode-pill,
    .src-opt span, .sys-check span,
    .ev-stop-btn, .diary-refresh-btn,
    .rg-refresh-btn, .gm-close, .modal-close {
        min-height: 44px;
    }
    /* Number boxes can stay compact width-wise but need taller hit areas */
    .num-box, .draw-input, .sys-input input {
        min-height: 38px;
    }
}


/* ─────────────────────────────────────────────────────────────────────
   📱 iPHONE-NARROW LAYOUTS  (≤ 480 px)
   Many panels are 2-column or 3-column grids — collapse to single column,
   and reduce the heaviest decorative layers.
   ───────────────────────────────────────────────────────────────────── */

@media (max-width: 480px) {

    /* Body padding tighter */
    body                 { font-size: 14px; }
    .page, section.page  { padding: 12px 10px !important; }

    /* Nav scrolls horizontally instead of wrapping */
    .nav-bar, .cockpit-nav, .nav-pills {
        overflow-x: auto;
        white-space: nowrap;
        scrollbar-width: none;
        -webkit-overflow-scrolling: touch;
    }
    .nav-bar::-webkit-scrollbar { display: none; }

    /* Punter form rows stack */
    .punter-actions      { grid-template-columns: 1fr !important; }
    .form-row            { flex-wrap: wrap; gap: 8px; }
    .num-boxes           { flex-wrap: wrap !important; }
    .num-box             { width: 42px !important; height: 42px !important;
                           font-size: 16px !important; }

    /* Bond seasons stack */
    .bond-seasons-strip  { grid-template-columns: 1fr !important; }

    /* Multi-column panels collapse */
    .kol-headline-row, .rg-stat-row, .friston-headline-row,
    .hawkes-stat-row, .conformal-stat-row, .lyap-stat-row,
    .glyph-panel-grid, .lab-grid, .arena-grid,
    .punter-vault-grid, .ce-grid {
        grid-template-columns: 1fr !important;
    }

    /* Trim heavy FX */
    .room-watermark      { font-size: 50vw !important; opacity: 0.035; }
    .ghost-onibi         { font-size: 22px; }
    body.ghost-breath::before { filter: blur(28px) !important; }
    /* Star Rift, Neural Arcs etc — fully off on iPhone-narrow */
    .star-rift, .neural-arcs, .crest-flare,
    .dimensional-fold, .ascension-burst { display: none !important; }

    /* Modals fill the screen with safe padding */
    .modal, .gm-modal, .upload-result-modal {
        margin: 8px !important;
        max-width: calc(100vw - 16px) !important;
        max-height: calc(100dvh - 16px) !important;
    }

    /* Lab education + aphorisms slightly smaller */
    .lab-edu-summary     { font-size: 12px; padding: 10px 12px; }
    .panel-aphorism      { font-size: 11px; }
    .panel-aphorism-voice { font-size: 9.5px; }
}


/* ─────────────────────────────────────────────────────────────────────
   📱 iPHONE-NARROW LAYOUT FIXES — Round 2 (2026-06-24)
   Targeted at the specific overflow problems Bocky photographed:
     · whole page scrolling horizontally (nav VAULT clipped, panels off-right)
     · glyph-spine runes piling on top of each other
     · pers-radio rows truncating the long-name alias
     · sys-row stretching Games/Sims off-screen
     · s2-grid showing only 2 of 4 columns
   FX layers intentionally untouched — Bocky loves the intensity.
   ───────────────────────────────────────────────────────────────────── */

@media (max-width: 480px) {

    /* ── ROOT GUARDS ───────────────────────────────────────────────────
       The cockpit was authored at 1280+ and several panels assume
       min-content widths that exceed the iPhone viewport. Clamp roots
       hard so no descendant can push horizontal scroll on the page. */
    html, body {
        overflow-x: hidden;
        max-width: 100vw;
    }
    .app, .cockpit, .page, section.page,
    .main-grid, .bottom-grid,
    .panel, .panel-voice, .panel-ppi, .panel-predconf,
    .panel-stage2, .panel-pulse {
        max-width: 100%;
        min-width: 0;       /* allow grid/flex children to actually shrink */
        box-sizing: border-box;
    }

    /* Reinforce the laptop-tier 1-col collapse — some panels were
       sneaking in min-widths via inline sizes. */
    .main-grid, .bottom-grid {
        grid-template-columns: 1fr !important;
    }

    /* ── VOICE OF THE ENGINE — glyph spine ─────────────────────────────
       The cells are <svg> elements with only a viewBox (no width/height
       attribute). iOS Safari treats such SVGs as intrinsic 300×150 — so
       min-content for the grid track is 300 px and 5 cells will not fit.
       Force the SVG to fluid sizing explicitly, and lock font-size on
       the inner text so the rune scales with the cell, not with the
       SVG's intrinsic dimensions. */
    .glyph-spine {
        grid-template-columns: repeat(5, minmax(0, 1fr)) !important;
        gap: 6px !important;
        margin: 4px 0 12px !important;
        max-width: 100%;
    }
    svg.glyph-cell {
        width: 100% !important;
        height: auto !important;
        max-width: 100% !important;
        min-width: 0 !important;
        aspect-ratio: 1 / 1;
        display: block;
    }
    .glyph-rune { font-size: 56px !important; }   /* still 56 in viewBox-units; SVG scales */
    .voice-quote { padding: 12px; }
    .voice-headline { font-size: 14px; }
    .voice-summary  { font-size: 12px; }

    /* ── PERSONALITY PICKER — show the full long-name alias ────────────
       Default .pers-radio is a single-row 4-col grid:
         [radio] [sym 28px] [name 1fr] [alias auto]
       On iPhone the alias gets pushed off-screen. Re-flow to 3 cols
       and let the alias drop to a second row spanning the name column,
       wrapping freely. */
    .pers-radio {
        grid-template-columns: auto 28px 1fr !important;
        grid-template-rows: auto auto;
        row-gap: 2px;
        padding: 8px 10px;
    }
    .pers-radio input { grid-row: 1 / span 2; grid-column: 1; }
    .pers-sym         { grid-row: 1 / span 2; grid-column: 2; }
    .pers-name        { grid-row: 1;          grid-column: 3; }
    .pers-tag         {
        grid-row: 2; grid-column: 3;
        white-space: normal;
        line-height: 1.3;
        font-size: 10.5px;
        opacity: 0.85;
    }

    /* ── SYSTEM CONFIG ROWS — stack icon + label + Games + Sims ────────
       Default .sys-row is 4 horizontal cells assuming ~520 px of space.
       Re-flow as: row 1 = icon + checkbox label, row 2 = Games + Sims
       side-by-side, both inputs full-width within their half. */
    .sys-row {
        grid-template-columns: 38px 1fr !important;
        grid-template-rows: auto auto;
        row-gap: 8px;
        padding: 10px 12px;
    }
    .sys-icon  { grid-row: 1; grid-column: 1; }
    .sys-check { grid-row: 1; grid-column: 2; min-width: 0; }
    .sys-check span { white-space: nowrap; }
    .sys-input {
        grid-row: 2;
        justify-content: space-between;
    }
    .sys-row .sys-input:nth-of-type(1) { grid-column: 1 / span 2; }
    .sys-row .sys-input:nth-of-type(2) { grid-column: 1 / span 2; }
    /* Both number inputs become wider so the value is fully visible */
    .sys-input input          { width: 100% !important; max-width: 140px; }
    .sys-input input#sys6Sims,
    .sys-input input#sys8Sims { width: 100% !important; max-width: 140px; }

    /* ── STAGE-2 SENSORY GRID — 4 cols → 2 cols ────────────────────────
       Default repeat(4, 1fr) shows S4 RMT and S8 MARTINGALE clipped. */
    .s2-grid {
        grid-template-columns: repeat(2, minmax(0, 1fr)) !important;
        gap: 8px !important;
    }
    .s2-item { min-width: 0; padding: 8px 10px; }
    .s2-name { font-size: 9.5px; letter-spacing: 0.5px; }

    /* ── ENGINE PULSE — keep at 2 cols (already collapses at 900 px),
       but make sure cards can shrink and the floating Greek symbol
       doesn't push width. */
    .pulse-cards          { grid-template-columns: repeat(2, minmax(0, 1fr)) !important;
                            gap: 8px !important; }
    .pulse-card           { min-width: 0; padding: 8px 10px 6px; overflow: hidden; }
    .pulse-card-symbol    { font-size: 18px; top: 4px; right: 6px; }
    .pulse-card-question  { font-size: 9.5px; height: auto; }
    .pulse-card-label     { font-size: 14px; }

    /* ── MACRO grid + BRAINSTEM rows — same overflow story ─────────── */
    .macro-grid    { grid-template-columns: repeat(2, minmax(0, 1fr)) !important; }
    .brainstem-row { grid-template-columns: 80px 1fr 48px !important; gap: 8px; }

    /* ── METRICS strip at top — drop to 2 cols ─────────────────────── */
    .metrics { grid-template-columns: repeat(2, minmax(0, 1fr)) !important; gap: 8px; }

    /* ── PREDCONF grid — left (picker) above right (sys + PRED) ────── */
    .predconf-grid { grid-template-columns: 1fr !important; gap: 14px; }
    .big-pred-btn  { width: 100% !important; max-width: 320px; }


    /* ── ENGINE MEMORY MODAL — title bar overflowed and hid the ✕ ────
       Default .mem-modal-head is a single flex row [title | meta | ✕].
       On iPhone the 22-px title eats the row and meta wraps weirdly,
       pushing the close button off-screen. Restructure: full-viewport
       card, title shrinks, meta moves below the title, ✕ pinned to
       the top-right corner of the card so it's always reachable. */
    .mem-modal-card {
        width: 100vw !important;
        height: 100dvh !important;
        max-width: 100vw !important;
        max-height: 100dvh !important;
        border-radius: 0;
        position: relative;
    }
    .mem-modal-head {
        flex-direction: column;
        align-items: flex-start;
        gap: 4px;
        padding: 14px 56px 12px 16px;   /* right padding reserves ✕ space */
        min-height: 0;
    }
    .mem-modal-title { font-size: 15px; letter-spacing: 0.2px; }
    .mem-modal-meta  { font-size: 10px; letter-spacing: 0.5px; }
    .mem-modal-close {
        position: absolute !important;
        top: 10px; right: 10px;
        width: 40px; height: 40px;
        background: rgba(212,175,55,0.10);  /* visible against header */
        font-size: 20px;
        z-index: 10;
    }
    .mem-modal-body table.mem-table { font-size: 10.5px; }


    /* ── ARENA PAGE — Round 2 (2026-06-24) ───────────────────────────
       Round 1 fixed the gross overflows. Bocky's image10-15 show the
       remaining problems: spirit-card grid still 2-col, hero title
       clipped, punter stats overflow, dual-pipeline quote clips, no
       visible cue that the weekly table is side-scrollable. */
    .page-arena              { padding: 12px 0 32px; }
    .arena-shell             { padding: 0 10px; max-width: 100% !important; }

    /* ── Arena countdown ── */
    .arena-countdown {
        grid-template-columns: 1fr !important;
        gap: 8px !important;
        padding: 12px 14px;
        text-align: center;
    }
    .ac-readout {
        flex-wrap: wrap;
        justify-content: center;
        gap: 10px;
    }

    /* ── Arena hero (四魂演武 title strip) ── */
    .arena-hero {
        grid-template-columns: 1fr !important;
        gap: 10px !important;
        padding: 14px 16px !important;
        text-align: left;
    }
    .arena-title { flex-wrap: wrap; gap: 10px; }
    .arena-glyph { font-size: 32px !important; }
    .arena-name  { font-size: 22px !important; letter-spacing: 0.5px !important; }
    .arena-sub   { font-size: 11px !important; }
    .arena-cycle-info {
        justify-content: flex-start !important;
        gap: 6px !important;
    }
    .ac-pill {
        min-width: 0 !important;
        padding: 4px 10px !important;
        flex: 1 1 auto;
    }
    .ac-pill .ac-label { font-size: 8.5px !important; letter-spacing: 1px !important; }
    .ac-pill .ac-value { font-size: 12px !important; }

    /* ── Arena arbitration verdict ── */
    .aa-head { flex-wrap: wrap; gap: 10px; }
    .aa-bars {
        display: grid !important;
        grid-template-columns: 1fr !important;
        gap: 6px;
    }
    .aa-bar {
        grid-template-columns: auto auto 1fr auto !important;
        gap: 8px;
        min-width: 0;
        padding: 6px 8px;
    }
    .aa-bar-wrap { min-width: 80px; }   /* ensure fill column has room */

    /* ── Wrap-level guards: nothing in Arena scrolls horizontally
       except the weekly table inside its own wrap ── */
    .arena-arbitration, .arena-dualpipe,
    .arena-prophecy-wrap, .arena-punter-wrap,
    .arena-weekly-wrap, .arena-leaderboard,
    .arena-spirit-grid, .arena-prophecy-spirits-wrap,
    .arena-elo-trajectory {
        min-width: 0;
        max-width: 100%;
        overflow-x: hidden;
    }

    /* ── Spirit verdict cards: force 1-col ── */
    .arena-spirit-grid,
    .arena-prophecy-spirits,
    .arena-elo-spirits {
        grid-template-columns: 1fr !important;
        gap: 10px !important;
    }
    .spirit-card {
        padding: 12px 14px;
        gap: 8px;
        min-width: 0;
    }
    .spirit-card-head     { flex-wrap: wrap; gap: 8px; }
    .spirit-kanji         { font-size: 22px !important; }
    .spirit-name          { font-size: 13px !important; }
    .spirit-role          { font-size: 10px !important; }
    .spirit-weapon-chip   { font-size: 9.5px !important; padding: 2px 7px; }
    .spirit-picks .sp-ball{ width: 24px; height: 24px; font-size: 10px; }

    /* ── Punter stats (CYCLES / TOTAL TFS / BEST WEEK) → 2-col grid ── */
    .punter-stats-card {
        grid-template-columns: repeat(2, 1fr) !important;
        padding: 10px 12px;
    }
    .ps-label { font-size: 8px !important; letter-spacing: 1.2px !important; }
    .ps-value { font-size: 15px !important; }
    /* vs-spirits rows stack 1-per-line */
    .ps-vs-grid { grid-template-columns: 1fr !important; gap: 5px; }
    .ps-vs-row  { font-size: 10.5px !important; padding: 4px 6px; }

    /* ── Punter ball grid: 15 → 7 per row (Saturday-lotto style) ── */
    .punter-ball-grid { grid-template-columns: repeat(7, 1fr) !important; }

    /* ── Draw strip (date + balls) ── */
    .arena-draw-strip {
        grid-template-columns: 1fr !important;
        gap: 10px !important;
        padding: 10px 14px !important;
    }

    /* ── Dual-pipeline panel ── */
    .arena-dualpipe          { padding: 12px !important; }
    .arena-dualpipe .dp-quote,
    .arena-dualpipe i,
    .arena-dualpipe em       { white-space: normal !important; }

    /* ── Leaderboard rows already shrink via 720px @media; just ensure
       they don't overflow horizontally on the tightest devices ── */
    .lb-row { min-width: 0; }
    .sb-row { min-width: 0; gap: 6px !important; }

    /* ── Weekly table: keep horizontal scroll, but add a visible cue
       so users know they can slide it ── */
    .weekly-table-wrap {
        overflow-x: auto;
        -webkit-overflow-scrolling: touch;
        position: relative;
        /* Right-edge gradient hints "swipe →" */
        -webkit-mask-image: linear-gradient(90deg,
            black 0, black calc(100% - 28px), transparent 100%);
                mask-image: linear-gradient(90deg,
            black 0, black calc(100% - 28px), transparent 100%);
    }
    .weekly-table-wrap::-webkit-scrollbar { height: 4px; }
    .weekly-table-wrap::-webkit-scrollbar-thumb {
        background: rgba(214,153,255,0.35);
        border-radius: 2px;
    }
    /* Inline hint chip pinned above the table */
    .arena-weekly-wrap::before {
        content: "← swipe to see more →";
        display: block;
        text-align: center;
        font-family: "JetBrains Mono", monospace;
        font-size: 9.5px;
        color: rgba(214,153,255,0.55);
        letter-spacing: 1.5px;
        margin: 4px 0 6px;
    }


    /* ── PERFORMANCE — disable expensive Safari iOS effects ──────────
       backdrop-filter is one of the most GPU-hungry CSS properties on
       Safari, and the cockpit uses it on 10+ modals and panels. On a
       phone-tier device it tanks scroll FPS. Strip it ≤480 only.
       Visual loss: panels lose the frosted blur behind them. Bocky's
       earlier ask to "keep the FX" still holds — the Star Rift / Neural
       Arcs / oni-bi etc. are untouched; only the cheap-looking blur
       fallback gets dropped. */
    .mem-modal, .vitals-modal, .gm-modal, .modal, .tc-overlay,
    .mac-overlay, .upload-result-modal,
    .panel-voice, .panel-ppi, .panel-predconf,
    .panel-stage2, .panel-pulse, .panel {
        backdrop-filter: none !important;
        -webkit-backdrop-filter: none !important;
    }
    /* Lighten the room watermark blur (was 28px on body.ghost-breath) */
    body.ghost-breath::before { filter: blur(16px) !important; }
    /* Skip-animation hint for users who opt out */
    @media (prefers-reduced-motion: reduce) {
        *, *::before, *::after {
            animation-duration: 0.001ms !important;
            animation-iteration-count: 1 !important;
            transition-duration: 0.001ms !important;
        }
    }


    /* ── HEADER ───────────────────────────────────────────────────────
       On desktop the header is a 3-column row: hero-left | nav (absolute
       centered) | hero-right. None of that fits on iPhone. Re-flow the
       whole header as a vertical stack — title row, nav row (wrapping),
       action row (PREDICT + regime + health). */
    header,
    header.cockpit-header,
    .cockpit-header,
    body > header {
        display: flex !important;
        flex-direction: column;
        align-items: stretch;
        gap: 8px;
        padding: 8px 10px 4px;
        position: relative;
    }
    .hero-left {
        display: flex !important;
        align-items: center;
        gap: 10px;
        justify-content: flex-start !important;
        /* Desktop CSS pins this to calc(50% − 280px) so the centered nav
           can't overlap it — on iPhone that calc evaluates negative and
           the crests visually float to nowhere. Restore full width. */
        max-width: 100% !important;
        min-width: 0;
        flex: 1 1 auto;
        width: 100%;
    }
    .hero-crests {
        display: flex; align-items: center; gap: 8px;
        margin-right: auto;   /* push everything else (title) toward right */
    }
    .crest-hanko, .crest-aml { height: 44px !important; }
    .hero-title { display: none; }  /* keep the row to one slim line on iPhone */
    .hero-title h1 { font-size: 16px; margin: 0; line-height: 1.1; }
    .hero-sub      { font-size: 10px; }

    /* ── NAV — wrap all 7 pills onto 2 rows, no scroll needed ──────── */
    nav.nav {
        position: static !important;
        left: auto !important;
        transform: none !important;
        display: flex !important;
        flex-wrap: wrap !important;
        justify-content: center;
        gap: 4px !important;
        padding: 4px !important;
        max-width: 100% !important;
        width: 100%;
        overflow: visible;
        mask-image: none;
        -webkit-mask-image: none;
    }
    .nav-pill {
        flex: 0 0 auto;
        padding: 5px 9px !important;
        font-size: 10px !important;
        letter-spacing: 0.6px !important;
        white-space: nowrap;
        border-radius: 999px;
        /* Keep tap target ≥36px via line-height + min-height */
        min-height: 30px;
        display: inline-flex;
        align-items: center;
    }

    /* ── HERO-RIGHT — PREDICT + regime badge + health, wrap to row ─── */
    .hero-right {
        display: flex !important;
        flex-wrap: wrap;
        justify-content: center;
        gap: 8px;
        width: 100%;
    }
    .predict-btn     { padding: 8px 16px !important; font-size: 12px !important; }
    .predict-label   { letter-spacing: 1px; }
    .regime-badge    { font-size: 10px !important; padding: 4px 10px !important; }
    .health-pill     { padding: 4px 10px !important; }
    .health-label    { font-size: 9px !important; }
    .health-val      { font-size: 12px !important; }


    /* ── VAULT TOOLBAR — wrap so Schema Map button is reachable ──────
       image17: pills + status + 🌌 Schema Map all in one horizontal row,
       Schema Map clipped off right. Re-flow as 3 stacked rows. */
    .panel-vault-toolbar {
        flex-wrap: wrap !important;
        padding: 10px 12px !important;
        gap: 8px !important;
    }
    .vault-engine-pills    { flex: 1 1 100%; justify-content: center; }
    .vault-toolbar-spacer  { display: none !important; }
    .vault-toolbar-status  { flex: 1 1 100%; text-align: center; font-size: 10px !important; }
    .vault-tool-btn        {
        flex: 1 1 100%;
        text-align: center;
        padding: 10px 16px !important;
        font-size: 13px !important;
    }
    .vault-engine-pill { padding: 7px 14px !important; font-size: 12px !important; }

    /* Vault body 3-col grid collapses to single column */
    .vault-body { grid-template-columns: 1fr !important; min-height: 0 !important; }


    /* ── SCHEMA MAP OVERLAY — make ✕ close reachable ─────────────────
       image16: the constellation overlay shows the canvas but no header
       — the 26px serif title + sub-text consume the row and push the
       ✕ close button off the right edge. Stack the header vertically
       AND pin the close absolute top-right as a safety net. */
    .vault-schema-map-header {
        flex-wrap: wrap;
        gap: 8px !important;
        padding: 10px 12px 10px 12px !important;
        padding-right: 96px !important;   /* reserves space for pinned ✕ */
        position: relative;
    }
    .vault-schema-map-title { font-size: 16px !important; flex: 1 1 100%; }
    .vault-schema-map-sub   { font-size: 10px !important; flex: 1 1 100%; }
    .vault-schema-map-controls {
        flex: 1 1 100%;
        justify-content: flex-start;
        gap: 8px;
    }
    .vault-map-btn { padding: 8px 14px !important; font-size: 12px !important; flex: 0 0 auto; }
    /* Belt-and-braces: pin the close button to top-right */
    #vaultMapClose {
        position: absolute !important;
        top: 8px; right: 8px;
        z-index: 20;
        padding: 8px 14px !important;
    }


    /* ── PUNTER HERO — shrink the gigantic "PUNTER BOX" title ────────
       image23: .punter-name was 38px serif with 4px letter-spacing
       and .punter-glyph was 48px floating emoji. Together they ate
       the top half of the screen on iPhone. Tighten both. */
    .punter-hero  { padding: 14px 12px !important; }
    .punter-title { gap: 10px !important; }
    .punter-glyph { font-size: 30px !important; }
    .punter-name  { font-size: 22px !important; letter-spacing: 2px !important; }
    .punter-sub   { font-size: 11px !important; letter-spacing: 1px !important; }


    /* ── PUNTER STATS chips — 5 chips fit cleanly on iPhone ─────────
       image23: SEALED/PENDING/WINNERS/JACKPOT/DEAD were 3+2. Force
       a clean 3-col grid so they wrap predictably. */
    .punter-stats {
        display: grid !important;
        grid-template-columns: repeat(3, 1fr) !important;
        gap: 6px !important;
    }
    .stat-chip { padding: 6px 4px !important; }
    .chip-num  { font-size: 16px !important; }
    .chip-lbl  { font-size: 9px !important; letter-spacing: 0.8px !important; }


    /* ── PUNTER · CHECK WINNERS num-boxes — same 4-col grid pattern
       as NEW TICKET. Round-2 fix only targeted .new-ticket-card; this
       extends the same treatment to .check-form-card so WINNING (6
       boxes → 4+2 grid) and SUPPS (2 boxes → 2-col) match visually. */
    .check-form-card .num-box-stack,
    .check-form-card .num-boxes {
        width: 100%;
    }
    .check-form-card .num-boxes {
        display: grid !important;
        grid-template-columns: repeat(4, 1fr) !important;
        flex-wrap: unset !important;
        overflow-x: hidden !important;
        gap: 8px !important;
        padding: 4px 0 !important;
        -webkit-mask-image: none !important;
                mask-image: none !important;
        scroll-snap-type: none;
    }
    /* SUPPS row only has 2 boxes — force 2-col centered for it */
    .check-form-card .supp-boxes {
        grid-template-columns: repeat(2, 1fr) !important;
        max-width: 50%;
    }
    .check-form-card .num-box,
    .check-form-card .win-box,
    .check-form-card .supp-box {
        flex: unset !important;
        width: 100% !important;
        min-width: 0 !important;
        height: 52px !important;
        font-size: 18px !important;
        border-radius: 10px !important;  /* match new-ticket rounded shape */
    }
    .check-form-card .form-label { flex: 1 1 100%; }
    /* CHECK WINNERS buttons stack vertically */
    .check-form-card .button-row { flex-direction: column; gap: 8px; }
    .check-form-card .button-row > * { width: 100%; }


    /* ── PUNTER VAULT — tighter ticket cards on iPhone ──────────────
       image26: cards are tall and the decorative gold side-bars
       (.punter-vault::before/::after) waste viewport width. Pull
       padding in, kill the side decoration on phone, smaller balls. */
    .punter-vault {
        padding: 12px 8px !important;
    }
    .punter-vault::before,
    .punter-vault::after { display: none !important; }   /* gold side-bars off on iPhone */

    .vault-card,
    .punter-vault-card,
    .ticket-card,
    .pv-ticket {
        padding: 10px 12px !important;
        margin-bottom: 10px !important;
    }
    .vault-card .ticket-balls,
    .pv-ticket .ticket-balls,
    .vault-card .pv-balls,
    .pv-ticket .pv-balls {
        gap: 6px !important;
    }
    .vault-card .ticket-ball,
    .vault-card .pv-ball,
    .pv-ticket .ticket-ball,
    .pv-ticket .pv-ball {
        width: 36px !important;
        height: 36px !important;
        font-size: 12px !important;
    }
    .vault-card .ticket-header,
    .pv-ticket .pv-header { font-size: 11px !important; }
    .vault-card .ticket-id,
    .pv-ticket .pv-id    { font-size: 11px !important; }
    .vault-card .ticket-result,
    .pv-ticket .pv-result { font-size: 11px !important; }


    /* ── PUNTER — NEW TICKET form rows ───────────────────────────────
       image18: SOURCE: label + 3 radios wrap as "Source: System 6" on
       row 1, "System 8 Mix" on row 2 — visually broken. Make label
       full-width on its own row, then the 3 radios in a clean strip. */
    .punter-card           { padding: 14px 14px 12px !important; }
    .new-ticket-card .form-row {
        flex-wrap: wrap;
        gap: 8px !important;
        margin-bottom: 12px !important;
    }
    .new-ticket-card .form-label {
        flex: 1 1 100%;
        min-width: 0 !important;
        font-size: 11px !important;
        letter-spacing: 1.5px !important;
        margin-bottom: 2px;
    }
    .new-ticket-card .source-row {
        gap: 8px !important;
        flex-wrap: wrap;
    }
    .new-ticket-card .src-opt {
        flex: 1 1 auto;
        justify-content: center;
        padding: 8px 10px !important;
        font-size: 12px !important;
        min-width: 0;
    }
    .draw-input { width: 100% !important; max-width: 100%; }

    /* ── Number boxes: clean 4×2 grid instead of the flex row ────────
       Round 1's flex-wrap produced the 5+3 layout. Use a proper grid
       so 8 boxes land as a balanced 4 × 2 (and 6 boxes as 4+2). */
    .new-ticket-card .num-box-stack { width: 100%; }
    .new-ticket-card .num-boxes {
        display: grid !important;
        grid-template-columns: repeat(4, 1fr) !important;
        flex-wrap: unset !important;
        overflow-x: hidden !important;
        gap: 8px !important;
        padding: 4px 0 !important;
        -webkit-mask-image: none !important;
                mask-image: none !important;
        scroll-snap-type: none;
    }
    .new-ticket-card .num-box {
        flex: unset !important;
        width: 100% !important;
        min-width: 0 !important;
        height: 52px !important;
        font-size: 18px !important;
    }
    /* Set-nav row centered — .nav-tip ("← / → to browse") is a keyboard
       hint that means nothing on a touchscreen, and letting it wrap onto
       a second line breaks the border-radius:999px pill into a stubby,
       badly-rounded blob (the pill radius is computed off the full
       2-row box height). Hide it on mobile so the row always stays one
       line and the pill renders cleanly. */
    .set-nav { flex-wrap: nowrap; gap: 8px; justify-content: center; }
    .nav-tip { display: none; }

    /* Button row stacks vertically — IMPORT + LOCK side-by-side is
       too cramped on iPhone */
    .new-ticket-card .button-row {
        flex-direction: column;
        gap: 8px;
    }
    .new-ticket-card .button-row > * { width: 100%; }


    /* ── LAB · FRISTON POLICIES TABLE — fit all 5 columns ────────────
       image19: ACTION / EFE / EPISTEMIC / PRAGMATIC / SOFTMAX% — the
       last col was clipped because SWITCH_PERSONALITY is a long label
       that pushes the action column wide. Shrink fonts + padding so
       all 5 cols fit on a 393px iPhone. */
    .fr-policies-card { padding: 12px !important; }
    .fr-policy-table {
        font-size: 10px !important;
        table-layout: fixed;
        width: 100%;
    }
    .fr-policy-table thead th {
        font-size: 8px !important;
        letter-spacing: 0.4px !important;
        padding: 4px 2px !important;
        white-space: nowrap;
    }
    .fr-policy-table td {
        padding: 6px 2px !important;
        font-size: 10px !important;
    }
    .fr-policy-action {
        font-size: 9px !important;
        letter-spacing: 0 !important;
        word-break: break-all;
    }
    .fr-policy-num,
    .fr-policy-efe,
    .fr-policy-epist,
    .fr-policy-pragm,
    .fr-policy-soft {
        font-size: 10px !important;
        text-align: right;
    }


    /* ── VAULT SCHEMA MAP — escape the stacking context once and for all
       image20: the overlay opens but the cockpit nav renders ABOVE it,
       and the close ✕ is unreachable. Root cause: our own apple_compat
       rule `.cockpit-nav { transform: translateZ(0); }` creates a new
       stacking context that fights the overlay's z-index:9000. Fix:
       (a) bump overlay to z-index:99999, (b) pin close button with
       position:fixed (escapes ALL contexts, attaches to viewport), and
       (c) make the close visually unmissable. */
    .vault-schema-map:not([hidden]) {
        z-index: 99999 !important;
        isolation: isolate;
    }
    .vault-schema-map-header {
        z-index: 100000 !important;
    }
    #vaultMapClose {
        position: fixed !important;
        top: max(12px, env(safe-area-inset-top)) !important;
        right: 12px !important;
        z-index: 100001 !important;
        width: 44px !important;
        height: 44px !important;
        padding: 0 !important;
        border-radius: 50% !important;
        background: rgba(212, 175, 55, 0.95) !important;
        color: #1a0e2a !important;
        /* Hide the HTML text "✕ close" — it doesn't fit in a 44px circle,
           leaks out as "lose". Render a single clean ✕ via pseudo. */
        font-size: 0 !important;
        font-weight: 700 !important;
        border: 2px solid rgba(0, 0, 0, 0.6) !important;
        box-shadow: 0 6px 18px rgba(0, 0, 0, 0.6),
                    0 0 24px rgba(212, 175, 55, 0.5) !important;
        display: flex !important;
        align-items: center !important;
        justify-content: center !important;
        line-height: 1 !important;
    }
    #vaultMapClose::before {
        content: "✕";
        font-size: 22px !important;
        line-height: 1;
        color: inherit;
    }
    /* Reheat button can stay in header — only close needs to escape */


    /* ── ROUND CLOSE BUTTONS — keep them ROUND on touch devices ──────
       image22 + Bocky 2026-06-27: many close buttons were authored as
       32×32 round, but our Apple-HIG rule above forces min-height:44px
       on touch — width stayed 32 → vertical oval. Match the width to
       keep them perfect circles. Apply to every round close button
       across the app (Bocky is finding them one at a time — batch all
       known classes so the next cousin doesn't break too). */
    .gm-close,
    .modal-close,
    .ev-stop-btn,
    .diary-refresh-btn,
    .rg-refresh-btn,
    .mem-modal-close,
    .hk-modal-close,         /* Royal Housekeeper Report */
    .chi-modal-close,        /* Chi-Square / Integrity Assessment */
    .vitals-modal-close,     /* Engine Vitals */
    .boot-greeting-close,    /* image27: diary/greeting popup ✕ */
    .upload-result-modal .modal-close,
    .gm-modal .gm-close,
    /* Generic catch-all: any button whose class ends in "-close"
       and uses border-radius:50% gets the same treatment */
    button[class$="-close"][class*="modal"],
    /* Broader catch-all for popup-style close buttons that don't
       have "modal" in the class name (image27 / boot-greeting) */
    button[class*="popup-close"],
    button[class*="greeting-close"] {
        min-width: 44px !important;
        width: 44px !important;
        height: 44px !important;
        aspect-ratio: 1 / 1 !important;
        padding: 0 !important;
    }


    /* ── PUNTER ANALYSIS REPORT card — fix description text overflow
       image28: .panar-card description ("A presentable, professional
       PDF analysis...") extends past the right edge of the viewport.
       Card itself needs width guard + text needs break-on-long-strings
       (the "20, 50, 100 draws" content with bold inline elements was
       confusing wrap calculation). */
    .panar-card {
        max-width: 100% !important;
        min-width: 0 !important;
        overflow: hidden !important;
        box-sizing: border-box;
    }
    .panar-desc {
        font-size: 12px !important;
        line-height: 1.5 !important;
        word-wrap: break-word !important;
        overflow-wrap: anywhere !important;
        max-width: 100% !important;
    }
    .panar-card .card-title {
        font-size: 17px !important;
        line-height: 1.2;
    }
    .panar-btn {
        max-width: 100% !important;
        padding: 10px 14px !important;
        font-size: 13px !important;
        word-wrap: break-word;
    }


    /* ── GLOSSARY personality cards — tighter on iPhone ──────────────
       glossary.css's base rule now caps kanji column at 96px; on iPhone
       96px is still 25% of viewport. Shrink kanji column + font so the
       body gets a comfortable reading width on the ~360-393px iPhone. */
    .gm-personality-grid {
        grid-template-columns: 1fr !important;
        gap: 10px !important;
    }
    .gm-personality-card {
        grid-template-columns: 64px 1fr !important;
        gap: 12px !important;
        padding: 14px 14px !important;
    }
    .gm-pc-kanji        { font-size: 42px !important; line-height: 1.05; }
    .gm-pc-title        { font-size: 17px !important; line-height: 1.2; }
    .gm-pc-verse        { font-size: 13px !important; padding-left: 10px; }
    .gm-pc-long         { font-size: 12.5px !important; line-height: 1.5; }
    .gm-pc-archetype    { font-size: 10px !important; }
    .gm-pc-domain       { font-size: 10px !important; }
    .gm-pc-literal      { font-size: 11px !important; padding: 5px 9px; }
    .gm-pc-coined       { font-size: 10px !important; padding: 5px 9px; }
    .gm-pc-drive        { font-size: 9.5px !important; padding: 2px 9px; }
    .gm-pc-romaji-word  { font-size: 14px !important; }
    .gm-pc-romaji-phon  { font-size: 9px !important; }
    .gm-pc-kanji-col    { padding: 0 2px !important; }
    .gm-pc-romaji       { min-width: 0 !important; }
}


/* ─────────────────────────────────────────────────────────────────────
   📱 iPAD-PORTRAIT LAYOUTS  (≤ 1024 px) — softer than iPhone-narrow
   The cockpit was designed for 1280+. iPad portrait is 768×1024 or
   810×1080. Mostly tighten grids; keep visual hierarchy.
   ───────────────────────────────────────────────────────────────────── */

@media (min-width: 481px) and (max-width: 1024px) {
    .punter-actions { grid-template-columns: repeat(2, 1fr) !important; }
    .kol-headline-row, .friston-headline-row {
        grid-template-columns: repeat(2, 1fr) !important;
    }
    .glyph-panel-grid { grid-template-columns: repeat(3, 1fr) !important; }
    .lab-grid         { grid-template-columns: repeat(2, 1fr) !important; }
    .arena-grid       { grid-template-columns: 1fr !important; }
    .ghost-onibi      { font-size: 24px; }
    .room-watermark   { font-size: 38vw !important; opacity: 0.04; }
}


/* ─────────────────────────────────────────────────────────────────────
   👻 TOUCH-MODE HAUNTINGS — adjustments when on a touch-only device.
   ghost-touch-mode is set on <body> by apple_compat.js once touch detected.
   ───────────────────────────────────────────────────────────────────── */

body.ghost-touch-mode .ghost-whisper {
    /* Whispers on touch are anchored to the bottom-center (no cursor) */
    left: 50% !important;
    top: auto !important;
    bottom: 100px !important;
    transform: translateX(-50%) !important;
}
body.ghost-touch-mode .ghost-whisper.show {
    transform: translateX(-50%) !important;
}

body.ghost-touch-mode .ghost-onibi {
    /* Tap (not hover) dissipates */
    pointer-events: auto;
}


/* ─────────────────────────────────────────────────────────────────────
   🩹 Misc iOS Safari quirks
   ───────────────────────────────────────────────────────────────────── */

/* Prevent input zoom on focus — Safari zooms in if font-size < 16px */
@media screen and (max-width: 1024px) {
    input, select, textarea {
        font-size: 16px !important;
    }
}

/* iOS Safari renders position:sticky with a 1px flicker — use translateZ
   to force a compositor layer on sticky elements */
.cockpit-nav, .nav-bar, .sticky {
    -webkit-transform: translateZ(0);
            transform: translateZ(0);
}

/* iOS Safari sometimes leaves a rubber-band overscroll on body. Lock it. */
html, body {
    overscroll-behavior-y: none;
}

/* PWA-installed mode (standalone) — hide any "open in safari" prompts that
   only make sense in the browser. */
@media all and (display-mode: standalone) {
    .browser-only { display: none !important; }
    /* Bottom nav has more breathing room when there's no URL bar */
    .nav-bar { padding-bottom: max(8px, env(safe-area-inset-bottom)); }
}
