/* ==========================================================================
   Abnormal FX — authenticated UI ("behind the login")
   Noir redesign. Fonts self-hosted; design system from the handoff base.css.
   Loaded ONLY by app_base.html — login, auth and the Flask index keep the
   original base.html styling untouched, per the design scope.
   ========================================================================== */

/* ---- self-hosted faces (no runtime Google Fonts) ---- */
@font-face{ font-family:'IBM Plex Mono'; font-weight:300; font-style:normal;
  font-display:swap; src:url('/static/fonts/plex-mono-300.woff2') format('woff2'); }
@font-face{ font-family:'IBM Plex Mono'; font-weight:400; font-style:normal;
  font-display:swap; src:url('/static/fonts/plex-mono-400.woff2') format('woff2'); }
@font-face{ font-family:'IBM Plex Mono'; font-weight:500; font-style:normal;
  font-display:swap; src:url('/static/fonts/plex-mono-500.woff2') format('woff2'); }
@font-face{ font-family:'IBM Plex Mono'; font-weight:600; font-style:normal;
  font-display:swap; src:url('/static/fonts/plex-mono-600.woff2') format('woff2'); }
@font-face{ font-family:'Libre Caslon Display'; font-weight:400; font-style:normal;
  font-display:swap; src:url('/static/fonts/libre-caslon-display-400.woff2') format('woff2'); }
@font-face{ font-family:'Libre Caslon Text'; font-weight:400; font-style:normal;
  font-display:swap; src:url('/static/fonts/libre-caslon-text-400.woff2') format('woff2'); }
@font-face{ font-family:'Libre Caslon Text'; font-weight:400; font-style:italic;
  font-display:swap; src:url('/static/fonts/libre-caslon-text-400i.woff2') format('woff2'); }

/* ==========================================================================
   Abnormal FX — Backend UI
   Proposed single stylesheet (drop into base.html, replace the old ~380 lines)
   Noir / black-and-white / one sell-red. Dark only.
   Fonts self-hosted as woff2 (see README > Fonts).
   ========================================================================== */

:root{
  /* ---- ink ---- */
  --ink:        #0a0a0b;   /* ground */
  --ink-2:      #101011;   /* window chrome, raised */
  --paper:      #ffffff;   /* primary text, "up/ok", printed buttons */
  --paper-dim:  #dbd8d2;   /* secondary text */
  --grey:       #b3afa7;   /* labels */
  --grey-2:     #928e86;   /* faint labels, timestamps */
  --grey-3:     #837f77;   /* eyebrow micro-labels */
  --sell:       #c33d31;   /* THE one accent — losses, danger, sells only */
  --sell-soft:  #e9a59d;   /* sell text on dark */

  --line:        rgba(233,228,215,.14);
  --line-soft:   rgba(233,228,215,.08);
  --line-strong: rgba(233,228,215,.20);
  --panel:       rgba(233,228,215,.02);   /* translucent card fill */
  --panel-2:     rgba(233,228,215,.015);

  --mono: 'IBM Plex Mono', ui-monospace, 'SFMono-Regular', Menlo, monospace;
  --serif:'Libre Caslon Display', Georgia, 'Times New Roman', serif;
  --serif-text:'Libre Caslon Text', Georgia, serif;

  --r: 0px;                 /* the system is hard-edged; corners are square */
}

*{ box-sizing:border-box }
html{ scroll-behavior:smooth }
body{
  margin:0;
  background:var(--ink);
  color:var(--paper);
  font-family:var(--mono);
  font-weight:300;
  line-height:1.55;
  -webkit-font-smoothing:antialiased;
}
a{ color:var(--paper); text-decoration:none }
a:hover{ color:#fff }
::selection{ background:var(--paper); color:var(--ink) }

/* ==========================================================================
   1. THE APP SURFACE  (every screen past landing + login)
   Wrap the page body in <div class="app"> ... </div>
   The bull photograph sits under an ~86% black wash; text stays crisp.
   ========================================================================== */
.app{
  position:relative;
  min-height:100vh;
  background-color:var(--ink);
  background-image:repeating-linear-gradient(114deg,
    transparent 0 46px, rgba(233,228,215,.014) 46px 48px);   /* venetian rake */
}
.app::before{                                                 /* the photograph */
  content:""; position:fixed; inset:0; z-index:0; pointer-events:none;
  background-image:
    linear-gradient(rgba(10,10,11,.84), rgba(10,10,11,.88)),
    url("/static/img/wall-st-bull.png");
  background-size:cover; background-position:center;
  filter:grayscale(1);
}
.app::after{                                                  /* grain + vignette */
  content:""; position:fixed; inset:0; z-index:0; pointer-events:none;
  background:radial-gradient(130% 120% at 50% 18%, transparent 52%, rgba(0,0,0,.7));
}
.app > *{ position:relative; z-index:1 }
@media (prefers-reduced-motion: reduce){ *{ animation:none !important } }

/* ==========================================================================
   2. NAV
   ========================================================================== */
.nav{ display:flex; align-items:center; justify-content:space-between;
  /* Safe-area aware: in installed (standalone) mode on iOS the page draws
     under the status bar/notch — pad the chrome, not the content. */
  padding:calc(14px + env(safe-area-inset-top, 0px)) calc(22px + env(safe-area-inset-right, 0px))
          14px calc(22px + env(safe-area-inset-left, 0px));
  border-bottom:1px solid var(--line) }
.nav__brand{ display:flex; align-items:center; gap:16px }
.nav__logo{ height:18px; width:auto; display:block }
.nav a{ padding:7px 13px; font-size:12px; letter-spacing:.04em; color:var(--grey) }
.nav a.is-active{ color:var(--paper); border-bottom:1px solid var(--paper) }

.role{ font-size:10px; letter-spacing:.16em; color:var(--paper-dim);
  border:1px solid var(--line-strong); padding:3px 8px }

/* ==========================================================================
   3. CARDS & LAYOUT
   ========================================================================== */
.card{ border:1px solid var(--line); background:var(--panel-2); padding:22px }
.card--key{ border-color:var(--line-strong); background:var(--panel) } /* emphasised */
.grid{ display:grid; gap:16px }
.eyebrow{ font-size:10px; letter-spacing:.2em; color:var(--grey);
  text-transform:uppercase }
.display{ font-family:var(--serif); font-weight:400; letter-spacing:.01em }
.note{ font-family:var(--serif-text); font-style:italic; color:var(--paper-dim) }

/* ==========================================================================
   4. STAT CELLS  (mono figures)
   ========================================================================== */
.stat__n{ font-size:20px; font-weight:500; letter-spacing:-.01em }
.stat__l{ font-size:10px; letter-spacing:.06em; color:var(--grey-2); margin-top:3px }
.big{ font-size:44px; font-weight:500; letter-spacing:-.02em; line-height:1 }
.up{ color:var(--paper) }     /* positive = bright paper, never green */
.down{ color:var(--sell-soft) }

/* ==========================================================================
   5. STATUS DOT + PILL
   ========================================================================== */
.s{ display:inline-block; width:8px; height:8px; border-radius:50%;
  background:var(--paper) }
.s--live{ background:var(--paper); animation:ring 2.8s ease-out infinite }
.s--degraded{ background:var(--sell) }
.s--down{ background:var(--sell); animation:pulse 1.1s infinite }
.pill{ display:inline-flex; align-items:center; gap:6px; padding:5px 10px;
  border:1px solid var(--line-strong); font-size:10px; letter-spacing:.1em }
.pill--sell{ border-color:var(--sell); color:var(--sell-soft) }

@keyframes pulse{ 0%,100%{opacity:1} 50%{opacity:.3} }
@keyframes ring{
  0%{ box-shadow:0 0 0 0 rgba(233,228,215,.4) }
  70%{ box-shadow:0 0 0 6px rgba(233,228,215,0) }
  100%{ box-shadow:0 0 0 0 rgba(233,228,215,0) } }

/* ==========================================================================
   6. BUTTONS
   ========================================================================== */
.btn{ display:inline-flex; align-items:center; justify-content:center;
  font-family:var(--mono); font-size:12px; letter-spacing:.06em;
  padding:12px 22px; border:1px solid transparent; cursor:pointer;
  background:transparent; -webkit-appearance:none; appearance:none;
  transition:border-color .12s ease, background .12s ease, color .12s ease }
.btn--ghost:hover{ border-color:var(--paper-dim); color:var(--paper) }
.btn--sell:hover{ background:rgba(195,61,49,.10) }
.btn--print:hover{ background:#fff }
.btn--print{ background:var(--paper); color:var(--ink); font-weight:600 }  /* primary */
.btn--ghost{ border-color:var(--line-strong); color:var(--paper-dim) }
.btn--sell{ border-color:var(--sell); color:var(--sell-soft) }             /* guarded */
.btn--sell-solid{ background:var(--sell); color:var(--paper); font-weight:600 }
.btn.small{ padding:6px 10px; font-size:10px }

/* ==========================================================================
   7. THE SIGNAL BAR  — the core idea: state ESCALATES by inversion.
   Healthy = a hairline you can ignore.  Down = the whole slab flips to
   paper (stop-press white-on-black) so it reads from across the room.
   ========================================================================== */
.signal{ display:flex; align-items:center; gap:14px;
  padding:14px 18px; border:1px solid var(--line-strong) }
.signal--degraded{ border-color:var(--sell); background:rgba(195,61,49,.08) }
.signal--down{                             /* INVERSION */
  border:0; background:var(--paper); color:var(--ink);
  padding:26px 28px; box-shadow:0 30px 80px -20px rgba(0,0,0,.7) }
.signal--down .display{ font-size:34px; line-height:1 }
.signal--down .btn--print{ background:var(--ink); color:var(--paper) }
.signal--down .btn--ghost{ border-color:var(--ink); color:var(--ink) }

/* ==========================================================================
   8. KEY–VALUE ROWS & TABLES
   ========================================================================== */
.kv{ display:flex; align-items:center; gap:10px; padding:12px 0;
  border-bottom:1px solid var(--line-soft) }
.kv:last-child{ border-bottom:0 }
.kv__k{ font-size:9px; letter-spacing:.14em; color:var(--grey-2) }

.tbl__head, .tbl__row{ display:grid; gap:12px; align-items:center;
  padding:15px 14px }
.tbl__head{ font-size:9px; letter-spacing:.14em; color:var(--grey-3);
  border-bottom:1px solid var(--line); padding:10px 14px }
.tbl__row{ border-bottom:1px solid var(--line-soft); font-size:13px }
.tbl__row--down{                           /* a down row inverts, in context */
  background:var(--paper); color:var(--ink); border:0; margin:2px 0 }

/* ==========================================================================
   9. REFERENCE DRAWER  — de-emphasised, dashed, "stops shouting"
   ========================================================================== */
.ref .card{ border-style:dashed }
.ref .eyebrow{ color:var(--grey-2) }

/* ==========================================================================
   10. WIZARD RAIL  (onboarding — kept)
   ========================================================================== */
.rail{ display:flex; align-items:center }
.rail__step{ display:flex; align-items:center; gap:10px }
.rail__dot{ width:28px; height:28px; border-radius:50%;
  border:1px solid var(--line-strong); display:flex; align-items:center;
  justify-content:center; font-size:12px; color:var(--paper-dim) }
.rail__step.is-done .rail__dot{ background:var(--paper); color:var(--ink); border:0 }
.rail__step.is-active .rail__dot{ border-color:var(--paper); color:var(--paper) }
.rail__line{ flex:1; height:1px; background:var(--line); margin:0 14px }
.rail__step.is-done + .rail__line,
.rail__line--done{ background:var(--line-strong) }

/* ==========================================================================
   11. BADGES  (admin queue counts)
   ========================================================================== */
.badge{ font-size:10px; padding:1px 7px; border-radius:10px;
  border:1px solid var(--line-strong); color:var(--paper-dim) }
.badge--alert{ background:var(--sell); color:var(--paper); border:0 }

/* ==========================================================================
   12. RESPONSIVE — add breakpoints as needed. Suggested: 1100px, 760px, 480px.
   Dense grids collapse to single column; the signal bar and any STOP/PAUSE
   action stay pinned within thumb reach on phones (position: sticky/bottom).
   ========================================================================== */

/* ==========================================================================
   13. SHARED PRIMITIVES  (layout glue the screens need on top of the system)
   ========================================================================== */
/* Viewport-proportional, not a fixed cap: a hard px ceiling strands the page
   in a narrow centre band the moment the window is very wide or the user
   zooms out (CSS viewport grows). 92vw keeps every screen — subscriber,
   provider, admin — filling the window at any size; the 1180px floor keeps
   laptops exactly as they were. Text/form content stays readable via its own
   inner caps (cards, ch-widths), not the shell. */
.shell{ max-width:max(1180px, 92vw); margin:0 auto;
  padding:26px clamp(16px,3vw,56px) 80px }
.stack{ display:flex; flex-direction:column }
.row-b{ display:flex; align-items:center; justify-content:space-between; gap:16px }
.wrap-flex{ display:flex; flex-wrap:wrap; gap:12px }
.muted{ color:var(--grey) }
.faint{ color:var(--grey-2) }
.hr{ height:1px; background:var(--line-soft); border:0; margin:0 }
.mono{ font-family:var(--mono) }

/* section heading used across screens */
.head{ display:flex; flex-direction:column; gap:8px; margin:34px 0 16px }
.head .display{ font-size:26px }
.head .lead{ color:var(--paper-dim); max-width:70ch; font-size:13px }

/* generic 2-col content grid, collapses on narrow */
.cols{ display:grid; gap:16px }
.cols--162{ grid-template-columns:1.62fr 1fr }
.cols--15{ grid-template-columns:1.5fr 1fr }
.cols--13{ grid-template-columns:1.3fr 1fr }
.cols--rail{ grid-template-columns:236px 1fr }
.tiles4{ display:grid; grid-template-columns:repeat(4,1fr); gap:1px;
  background:var(--line-soft); border:1px solid var(--line-soft) }
.tiles4 > *{ background:var(--ink); padding:16px 18px }

/* ---- forms, noir ---- */
.field{ display:flex; flex-direction:column; gap:7px; margin-bottom:14px }
label{ font-size:10px; letter-spacing:.14em; text-transform:uppercase;
  color:var(--grey); }
/* Match bare inputs too: an <input> with no type attribute defaults to text
   but is NOT matched by input[type=text], which left those fields with the
   browser's white default. */
input:not([type=checkbox]):not([type=radio]):not([type=submit]):not([type=button]):not([type=file]),
select, textarea{
  font-family:var(--mono); font-size:13px; color:var(--paper);
  background:var(--ink-2); border:1px solid var(--line); border-radius:0;
  padding:11px 12px; width:100%; -webkit-appearance:none; appearance:none; }
input:focus, select:focus, textarea:focus{ outline:0; border-color:var(--paper-dim) }
input::placeholder, textarea::placeholder{ color:var(--grey-3) }
input[type=checkbox], input[type=radio]{ accent-color:var(--paper); }
/* Autofill paints its own near-white background; force it back to the ground. */
input:-webkit-autofill, textarea:-webkit-autofill, select:-webkit-autofill{
  -webkit-text-fill-color:var(--paper);
  -webkit-box-shadow:0 0 0 1000px var(--ink-2) inset;
  caret-color:var(--paper); }

/* ---- flash ---- */
.flashes{ display:flex; flex-direction:column; gap:8px; margin-bottom:18px }
.flash{ border:1px solid var(--line-strong); background:var(--panel);
  padding:12px 14px; font-size:12px; color:var(--paper) }

/* ---- footer ---- */
.foot{ border-top:1px solid var(--line); margin-top:56px;
  padding:22px clamp(16px,4vw,28px) calc(22px + env(safe-area-inset-bottom, 0px));
  display:flex; flex-wrap:wrap; gap:12px;
  justify-content:space-between; align-items:center;
  font-size:11px; color:var(--grey-2) }
.foot a{ color:var(--paper-dim) }

/* ---- responsive ---- */
@media (max-width:980px){
  .cols--162,.cols--15,.cols--13,.cols--rail{ grid-template-columns:1fr }
  .tiles4{ grid-template-columns:repeat(2,1fr) }
}
@media (max-width:560px){
  .tiles4{ grid-template-columns:1fr }
  .nav{ padding:12px 14px }
}

/* ==========================================================================
   14. VIDEO BACKDROP  (skyline) — public pages that want motion instead of
   the bull still. Set body class "video-bg" and drop the markup into the
   app_base {% block backdrop %}. The video's own scrims replace the bull
   wash and vignette, so those pseudo-elements are hidden for these pages.
   ========================================================================== */
.app-video{ position:fixed; inset:0; overflow:hidden; pointer-events:none }
.app > .app-video{ z-index:0 }
.app-video video{ width:100%; height:100%; object-fit:cover; filter:grayscale(1) }
.app-video .scrim{ position:absolute; inset:0 }
.app-video .scrim.linear{
  background:linear-gradient(rgba(10,10,11,.74), rgba(10,10,11,.90)) }
.app-video .scrim.vignette{
  background:radial-gradient(130% 120% at 50% 16%, transparent 50%, rgba(0,0,0,.80)) }
body.video-bg .app::before,
body.video-bg .app::after{ display:none }
@media (prefers-reduced-motion: reduce){ .app-video video{ display:none } }

/* ==========================================================================
   15. SINGLE-SCREEN PAGES  (body.single) — lock a page to one viewport.
   nav + footer take natural height, the shell fills the rest and centres its
   content. Escape hatch: on a viewport too short to hold the content, it
   releases to normal scrolling rather than clipping.
   ========================================================================== */
body.single{ height:100vh; overflow:hidden }
body.single .app{ height:100vh; display:flex; flex-direction:column }
body.single .shell{ flex:1 1 auto; min-height:0;
  display:flex; flex-direction:column; justify-content:center;
  padding-top:16px; padding-bottom:16px }
body.single .foot{ margin-top:0 }
@media (max-height:680px){
  body.single{ height:auto; overflow:auto }
  body.single .app{ height:auto; min-height:100vh }
  body.single .shell{ justify-content:flex-start }
}

/* ==========================================================================
   16. LEGACY COMPAT — the old base.html class vocabulary, restyled noir so a
   page converts by switching to app_base without re-authoring every element.
   These class names appear ONLY on not-yet-redesigned pages; the finished
   noir pages use the modifier classes above, so this cannot affect them.
   No gold anywhere: positive = paper, negative = oxblood, never green.
   ========================================================================== */
.sub{ color:var(--paper-dim); font-size:13px }
.gold{ color:var(--paper) }                 /* retire gold text -> paper */

/* buttons: bare .btn = primary paper; the old variants map to noir */
.btn:not([class*="btn--"]){ background:var(--paper); color:var(--ink);
  font-weight:600; border-radius:0 }
.btn.secondary{ background:transparent; color:var(--paper-dim);
  border:1px solid var(--line-strong) }
.btn.danger{ background:transparent; color:var(--sell-soft);
  border:1px solid var(--sell) }

/* page head */
.page-head{ display:flex; align-items:flex-end; justify-content:space-between;
  gap:16px; flex-wrap:wrap; margin:18px 0 20px }
.page-head h1{ font-family:var(--serif); font-weight:400;
  font-size:clamp(28px,4vw,40px); letter-spacing:.01em; margin:6px 0 2px }

/* stat tiles */
.tiles{ display:grid; gap:1px; background:var(--line-soft);
  border:1px solid var(--line-soft);
  grid-template-columns:repeat(auto-fit,minmax(140px,1fr)); margin:16px 0 }
.tile{ background:var(--ink); padding:16px 18px }
.tile.hero{ background:var(--panel) }
.tile .k{ font-size:10px; letter-spacing:.06em; color:var(--grey-2);
  text-transform:uppercase }
.tile .v{ font-size:20px; font-weight:500; margin-top:4px; color:var(--paper) }
.stat-n{ font-size:20px; font-weight:500; color:var(--paper) }

/* pills (extends the base .pill) */
.pill.ok, .pill.gold{ border-color:var(--line-strong); color:var(--paper) }
.pill.dot::before{ content:""; width:6px; height:6px; border-radius:50%;
  background:currentColor; display:inline-block }

/* status pill + dots */
.statuspill{ display:inline-flex; align-items:center; gap:7px; padding:4px 10px;
  border:1px solid var(--line-strong); font-size:11px; color:var(--paper-dim) }
.statuspill .d, .s .d{ width:7px; height:7px; border-radius:50%;
  background:var(--paper); display:inline-block }
.s{ display:inline-flex; align-items:center; gap:9px; color:var(--paper-dim);
  font-size:12px; white-space:nowrap }
.s .d{ flex-shrink:0 }
/* engine status rows: align the dots + values into a clean column */
.estatus .row{ display:grid; grid-template-columns:1fr 116px; align-items:center; gap:12px }
.estatus .row > span:first-child{ min-width:0 }
.estatus .row .s{ justify-content:flex-start }
.s-ok{ color:var(--paper) } .s-off{ color:var(--grey-2) }
.s-guard{ color:var(--paper) }
.s-ok .d{ background:var(--paper) } .s-off .d{ background:var(--grey-2) }
.s-guard .d{ background:var(--paper) }

/* rows / kv */
.row{ display:flex; align-items:center; justify-content:space-between; gap:10px;
  padding:10px 0; border-bottom:1px solid var(--line-soft); font-size:13px }
.row:last-child{ border-bottom:0 }
.kv .k, .row .k{ color:var(--grey-2); font-size:11px; letter-spacing:.04em }

/* callouts / warnings / trust */
.callout{ border:1px solid var(--line-strong); background:var(--panel);
  padding:12px 14px; font-size:13px }
.warn{ color:var(--sell-soft) }
.trust{ border-left:2px solid var(--sell); padding-left:12px;
  color:var(--paper-dim); font-size:12px }

/* P&L colours — paper up, oxblood down, never green */
.pos{ color:var(--paper) } .neg{ color:var(--sell-soft) }

/* sub-navigation tabs */
.subnav{ display:flex; gap:8px; flex-wrap:wrap; margin-bottom:16px }
.subnav a{ padding:6px 12px; font-size:11px; color:var(--grey);
  border:1px solid var(--line) }
.subnav a:hover, .subnav a.on{ color:var(--paper); border-color:var(--line-strong) }

/* bare tables (finished pages use .tape and are unaffected) */
.shell table:not(.tape){ width:100%; border-collapse:collapse; font-size:13px }
.shell table:not(.tape) th{ text-align:left; font-size:9px; letter-spacing:.14em;
  text-transform:uppercase; color:var(--grey-3); padding:9px 10px;
  border-bottom:1px solid var(--line) }
.shell table:not(.tape) td{ padding:11px 10px;
  border-bottom:1px solid var(--line-soft); color:var(--paper-dim) }

/* ==========================================================================
   17. ONBOARDING WIZARD — its .rail is a vertical column and collides with
   the horizontal .rail in §10, so every rule is scoped under .wizard to win.
   ========================================================================== */
.wizard{ display:grid; grid-template-columns:1fr 1fr; gap:44px;
  align-items:start; margin-top:20px }
.wizard .rail{ display:block; position:sticky; top:24px; align-items:initial }
.wizard .rail .eyebrow{ display:inline-flex; align-items:center; gap:10px }
.wizard .rail h1{ font-family:var(--serif); font-weight:400;
  font-size:clamp(30px,4vw,44px); letter-spacing:.01em; margin:12px 0 10px }
.wizard .rail > p{ color:var(--paper-dim); font-size:14px }
.wizard .rail ul{ list-style:none; padding:0; margin:18px 0;
  display:flex; flex-direction:column; gap:10px }
.wizard .rail ul li{ display:flex; gap:12px; font-size:13px; color:var(--paper-dim) }
.wizard .rail ul li::before{ content:"—"; color:var(--grey); flex-shrink:0 }
.stepnum{ display:inline-flex; align-items:center; justify-content:center;
  width:22px; height:22px; border:1px solid var(--line-strong);
  font-size:11px; color:var(--paper-dim) }
.progress{ display:flex; gap:6px; margin:18px 0 }
.progress i{ width:24px; height:3px; background:var(--line); display:block }
.progress i.on{ background:var(--paper) }
.acct{ display:flex; align-items:center; justify-content:space-between; gap:12px;
  border:1px solid var(--line); padding:14px 16px; margin:14px 0 }
.block, .wrapblock{ font-family:var(--mono); font-size:12px;
  background:rgba(0,0,0,.4); border:1px solid var(--line-soft);
  padding:11px 12px; word-break:break-all }
@media (max-width:860px){
  .wizard{ grid-template-columns:1fr; gap:24px }
  .wizard .rail{ position:static } }

/* ==========================================================================
   18. MOBILE — tables were forcing the whole page wider than the viewport
   (you had to zoom out). Make every table scroll inside its own box, tighten
   the shell padding, and let the engine status column shrink.
   ========================================================================== */
.shell table{ display:block; max-width:100%; overflow-x:auto;
  -webkit-overflow-scrolling:touch }
/* Grid/flex children default to min-width:auto (content size), so a wide table
   grows its whole column and the page with it. Let them shrink so the table
   scrolls inside instead. */
.card, .cols > *, .stack > *, .cols--162 > *, .cols--15 > *,
.cols--13 > *, .cols--rail > *{ min-width:0 }
/* Backstop: nothing may push the page wider than the phone. Internal
   scrollers (tables) still scroll; this only clips stray overflow so the
   user never has to zoom out. */
.app{ overflow-x:clip }
.pcell, .planner-grid > *{ min-width:0 }
@media (max-width:640px){
  .shell{ padding-left:14px; padding-right:14px }
  .estatus .row{ grid-template-columns:1fr auto; gap:14px }
  .cols, .cols--162, .cols--15, .cols--13, .cols--rail{ grid-template-columns:1fr }
  .tiles4{ grid-template-columns:1fr }
  .planner-grid{ grid-template-columns:1fr }
  .head .display, h1.display{ font-size:clamp(30px,8vw,40px) }
}
