/* ============================================================
   SUPERCOMMUTE — "Timetable" design system (LOCKED, spec v2 §3.1)
   The exact five tokens. Flat by rule: no rounded corners, no shadow
   effects, no colour blends. Hierarchy is size and rules only.
   Fonts are self-hosted woff2, served only from this origin.
   ============================================================ */

@font-face {
  font-family: "Archivo Black";
  src: url("/fonts/archivo-black-400.woff2") format("woff2");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Inter";
  src: url("/fonts/inter-400.woff2") format("woff2");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Inter";
  src: url("/fonts/inter-500.woff2") format("woff2");
  font-weight: 500;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Inter";
  src: url("/fonts/inter-600.woff2") format("woff2");
  font-weight: 600;
  font-style: normal;
  font-display: swap;
}

:root {
  --paper: #ffffff; /* Paper  #FFFFFF */
  --ink: #0a0a0a; /* Ink    #0A0A0A */
  --red: #e30613; /* Signal Red #E30613 */
  --rule: #eaeaea; /* Rule   #EAEAEA */
  --sec: #6b6b6b; /* Secondary #6B6B6B */
  --display: "Archivo Black", "Arial Black", Impact, sans-serif;
  --body: "Inter", -apple-system, "Helvetica Neue", Arial, sans-serif;
}

/* ============================================================
   Timetable app layout (spec v2 §3.2). Swiss grid, mobile-first.
   Flatness is enforced: every reset zeroes the corner radius; there are
   no shadow effects and no colour blends anywhere (the bundle test proves it).
   ============================================================ */

* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
  border-radius: 0;
}
html {
  -webkit-text-size-adjust: 100%;
}
body {
  background: var(--paper);
  color: var(--ink);
  font-family: var(--body);
  font-size: 15px;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
}
a {
  color: inherit;
}
a:focus-visible,
button:focus-visible,
input:focus-visible,
select:focus-visible,
textarea:focus-visible {
  outline: 2px solid var(--ink);
  outline-offset: 3px;
}
button {
  font-family: var(--body);
  cursor: pointer;
}
input {
  font-family: var(--body);
  font-size: 15px;
}

/* ---- layout: 12-col, max 1240px, 20px gutters ---- */
.wrap {
  max-width: 1240px;
  margin: 0 auto;
  padding: 0 20px;
}
.section {
  border-top: 2px solid var(--ink);
  padding: 24px 0 36px;
}
.grid12 {
  display: grid;
  grid-template-columns: repeat(12, 1fr);
  gap: 20px;
}

/* ---- type ---- */
.display {
  font-family: var(--display);
  letter-spacing: -0.05em;
  line-height: 0.95;
  font-weight: 400;
}
.kicker {
  font-size: 12px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--red);
  margin-bottom: 12px;
}
.label {
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--sec);
}

/* ---- nav ---- */
.nav {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 16px 0;
  gap: 16px;
}
.wordmark {
  font-family: var(--display);
  letter-spacing: -0.04em;
  font-size: 20px;
  display: inline-flex;
  align-items: center;
  gap: 8px;
}
.wordmark .sq {
  display: inline-block;
  width: 12px;
  height: 12px;
  background: var(--red);
}
.navlinks {
  display: flex;
  gap: 20px;
  align-items: center;
}
.navlink {
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  text-decoration: none;
  color: var(--ink);
  padding-bottom: 2px;
  border-bottom: 2px solid transparent;
}
.navlink[aria-current="page"] {
  border-bottom-color: var(--red);
}
.alertbadge {
  font-size: 11px;
  font-weight: 600;
  color: var(--paper);
  background: var(--red);
  padding: 2px 7px;
  min-width: 20px;
  text-align: center;
  text-decoration: none; /* the badge is a <span> inside the ALERTS link (PRD-0034 R8) */
}
.alertbadge[hidden] {
  display: none;
}

/* ---- big-numeral tiles (the imagery) ---- */
.tiles {
  display: grid;
  grid-template-columns: 1fr;
  gap: 0;
  border-left: 1px solid var(--rule);
}
.tile {
  border-top: 1px solid var(--rule);
  border-right: 1px solid var(--rule);
  border-bottom: 1px solid var(--rule);
  padding: 16px;
  /* PRD-0026 AC8 (F-6): a tile is a link but keeps the same visual weight. */
  display: block;
  text-decoration: none;
  color: inherit;
}
.tile .num {
  font-family: var(--display);
  font-size: clamp(40px, 12vw, 64px);
  line-height: 1;
  letter-spacing: -0.05em;
}
.tile .num.hot {
  color: var(--red);
}
.tile .cap {
  margin-top: 8px;
}

/* ---- status hero ---- */
.hero {
  padding: 8px 0 4px;
}
.hero .headline {
  font-size: clamp(28px, 6vw, 44px);
}

/* ---- tables (Timetable, Bookings) ---- */
.table {
  width: 100%;
  border-collapse: collapse;
}
.table thead th {
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--sec);
  text-align: left;
  padding: 8px 10px;
  border-bottom: 2px solid var(--ink);
}
.table tbody td {
  padding: 12px 10px;
  border-bottom: 1px solid var(--rule);
  vertical-align: top;
}
.table tbody tr:hover {
  background: #fafafa;
}
.num-cell {
  font-family: var(--display);
  letter-spacing: -0.03em;
}
.muted {
  color: var(--sec);
}

/* ---- rectangular status chips (never rounded) ---- */
.chip {
  display: inline-block;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  padding: 3px 8px;
  border-radius: 0;
}
.chip.ok {
  background: var(--rule);
  color: var(--ink);
}
.chip.rd {
  background: var(--red);
  color: var(--paper);
}
.chip.line {
  background: var(--paper);
  color: var(--ink);
  border: 2px solid var(--ink);
}
/* PRD-0031 R2: the provenance chip (LIVE / SEED / MANUAL / DIRECT) — a compact
   `.ok` chip beside its row's other chips; text on every chip, tokens only. */
.chip.src {
  font-size: 10px;
  padding: 2px 6px;
  letter-spacing: 0.06em;
}

/* ---- buttons ---- */
.btn {
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  padding: 10px 16px;
  border: 0;
  background: var(--ink);
  color: var(--paper);
}
.btn:hover {
  background: var(--red);
}
.btn.line {
  background: var(--paper);
  color: var(--ink);
  border: 2px solid var(--ink);
  /* P2: the spec-literal inset treatment, expressed WITHOUT a box-shadow (the
     flat-rule bundle test forbids box-shadow). A resting inner rule (outline
     pulled inside with a negative offset) gives the outlined button its
     inset-line look; :focus-visible above overrides with the outer focus ring. */
  outline: 1px solid var(--ink);
  outline-offset: -5px;
}
.btn.line:hover {
  background: var(--ink);
  color: var(--paper);
}

/* ---- forms ---- */
.field {
  display: block;
  margin-bottom: 12px;
}
.field input,
.field textarea {
  width: 100%;
  padding: 10px;
  border: 2px solid var(--ink);
  background: var(--paper);
  color: var(--ink);
  font-family: var(--body);
  font-size: 15px;
}

/* ---- empty state ---- */
.empty {
  color: var(--sec);
  padding: 24px 0;
}

/* ---- shared async state: loading / error / expired (PRD-0019 AC1) ----
   The one state layer every screen renders through. Loading is a mechanical
   uppercase kicker (no spinner, §3 motion); .error is Signal-Red (a token, so
   the flat/token bundle scan still passes) and is declared AFTER .label so a
   `class="error label"` node is red, not the gray Secondary it fell through to. */
.loading {
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--sec);
  padding: 8px 0;
}
.error {
  color: var(--red);
}
.expired,
.boot-error {
  padding: 16px 0;
}
.expired .btn,
.boot-error .btn {
  margin-top: 10px;
}

/* ---- staleness line (PRD-0019 P8) ---- */
.staleness {
  padding: 16px 0 0;
}

/* ---- budget & gate board (PRD-0022) ---- */
/* The gate tile hero: RATIO in Archivo Black; Signal Red below the 2.0 gate (a
   token, so the flat/token bundle scan still passes — red is the meaning, not a flood). */
.gate {
  border: 2px solid var(--ink);
  padding: 20px 16px;
  margin: 12px 0 24px;
}
.gate .ratio {
  display: flex;
  align-items: baseline;
  gap: 12px;
}
.gate .ratio-label {
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--sec);
}
.gate .ratio-num {
  font-family: var(--display);
  font-size: clamp(48px, 14vw, 88px);
  line-height: 1;
  letter-spacing: -0.05em;
}
.gate .ratio.below .ratio-num {
  color: var(--red);
}
.gate .gate-line {
  margin-top: 8px;
  font-weight: 600;
  color: var(--ink);
}
.gate .gate-meta {
  margin-top: 4px;
}

/* Monthly cash bars vs the $2,500 line — rules + numeral weight, no chart library,
   no gradient. The track is a rule; the fill is Ink; the budget line is the track's
   right border; an over-budget month tints its numeral red (the .num.hot precedent). */
.bars {
  margin-bottom: 24px;
}
.bar {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 6px 0;
}
.bar-label {
  flex: 0 0 88px;
}
.bar-track {
  flex: 1 1 auto;
  height: 20px;
  background: var(--rule);
  border-right: 2px solid var(--ink);
}
.bar-fill {
  display: block;
  height: 100%;
  background: var(--ink);
}
.bar-num {
  flex: 0 0 auto;
  font-size: 18px;
}
.bar-num.hot {
  color: var(--red);
}
.budget-totals,
.points-note {
  margin-top: 8px;
}

/* Savings by ledger category — the two structural categories read $0 (muted). */
.cat-rows {
  margin-bottom: 24px;
}
.cat-row {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  padding: 8px 0;
  border-bottom: 1px solid var(--rule);
}
.cat-row.muted {
  color: var(--sec);
}
.cat-row .cat-amount {
  font-size: 18px;
}

/* The per-week table head carries the Export CSV control (AC4). */
.week-savings-head {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 12px;
}
.week-savings .evidence {
  display: block;
  margin-top: 4px;
}

/* ---- footer ---- */
.foot {
  border-top: 2px solid var(--ink);
  padding: 20px 0 40px;
  font-size: 12px;
  color: var(--sec);
}

/* ---- responsive: phone at the gate is primary; widen up ---- */
@media (min-width: 720px) {
  .tiles {
    grid-template-columns: repeat(5, 1fr);
  }
  /* Desktop keeps the nav row (PRD-0026 AC5); the mobile shell is hidden. */
  .hamburger {
    display: none;
  }
  .nav-sheet {
    display: none;
  }
  .header-record {
    display: none;
  }
  .record-chooser {
    display: none;
  }
}
@media (max-width: 719px) {
  /* PRD-0026 AC1: the wrapped link-pile is replaced by the hamburger + sheet. */
  .navlinks {
    display: none;
  }
  .hamburger {
    display: flex;
  }
  /* AC6: RECORD is reachable from the header at phone width. */
  .header-record {
    display: inline-flex;
  }
  /* The phone fits (PRD-0019 AC4): the header wraps instead of forcing a
     horizontal body scroll, and every nav link is a >=44px tap target. */
  .nav {
    flex-wrap: wrap;
  }
  .navlink {
    display: inline-flex;
    align-items: center;
    min-height: 44px;
    padding: 10px 4px 8px;
  }
  .table thead {
    display: none;
  }
  .table tbody td {
    display: block;
    border-bottom: 0;
    padding: 4px 0;
  }
  .table tbody tr {
    display: block;
    border-bottom: 1px solid var(--rule);
    padding: 12px 0;
  }
  /* Mobile tables keep meaning (AC4/F5): the collapsed head is replaced by a
     per-cell label from `data-label`, so nightly/total/conf#/cancel-by stay
     tellable apart (Bookings first). Text content, so the flat rule is unaffected. */
  .table tbody td[data-label]::before {
    content: attr(data-label) ": ";
    font-size: 11px;
    font-weight: 600;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--sec);
    margin-right: 6px;
  }
}
/* Header condense at the narrowest phones (<=375px): the wordmark and nav each
   take a full row, so nothing overflows the viewport width (AC4). */
@media (max-width: 375px) {
  .nav {
    flex-direction: column;
    align-items: flex-start;
    gap: 8px;
  }
}

/* --- PRD-0026 mobile nav shell -------------------------------------------
   Hamburger + full-height flat sheet at phone width (the desktop nav row stays,
   AC5). The sheet APPEARS — no slide/easing (§3 motion). Flat by rule: the five
   tokens only, no radius/shadow/gradient. `display` is toggled per breakpoint
   above; the `[hidden]` attribute owns the closed state (AC1). */
.hamburger {
  display: none; /* desktop default; the >=720px block hides it, <=719px shows it */
  flex-direction: column;
  justify-content: center;
  gap: 5px;
  width: 44px;
  min-height: 44px;
  padding: 0;
  border: 0;
  background: transparent;
  cursor: pointer;
}
.hamburger-bar {
  display: block;
  width: 22px;
  height: 2px;
  background: var(--ink);
}
.nav-sheet {
  position: fixed;
  inset: 0;
  z-index: 50;
  display: flex;
  justify-content: flex-end;
}
/* A `display` on `.nav-sheet` overrides the `hidden` attribute's UA style, so the
   closed state must be reasserted at higher specificity (AC1). */
.nav-sheet[hidden] {
  display: none;
}
.nav-sheet-backdrop {
  position: absolute;
  inset: 0;
  background: var(--ink);
  opacity: 0.4; /* a flat scrim — opacity, never a shadow or gradient */
}
.nav-sheet-panel {
  position: relative;
  width: 100%;
  max-width: 380px;
  height: 100%;
  margin-left: auto;
  padding: 16px;
  background: var(--paper);
  border-left: 1px solid var(--rule);
  overflow-y: auto;
}
.nav-sheet-head {
  display: flex;
  justify-content: flex-end;
  align-items: center;
  min-height: 44px;
  margin-bottom: 8px;
}
.nav-sheet-close {
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  min-height: 44px;
  padding: 10px 12px;
  border: 0;
  background: transparent;
  color: var(--ink);
  cursor: pointer;
}
.nav-sheet-items {
  display: flex;
  flex-direction: column;
}
.sheet-item {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
  min-height: 44px;
  padding: 12px 0;
  border-top: 1px solid var(--rule);
  text-decoration: none;
  color: var(--ink);
}
.sheet-item-label {
  font-family: var(--display);
  letter-spacing: -0.02em;
  font-size: 18px;
}
.sheet-item-desc {
  text-align: right;
}
/* AC4: the aria-current red rule extends to sheet items (a Signal-Red left rule,
   the token — reusing the existing marked-active affordance). */
.sheet-item[aria-current="page"] {
  border-left: 3px solid var(--red);
  padding-left: 9px;
}
/* PRD-0029 AC1: the account item leads with the identity initial — a flat Ink
   square with a Paper glyph (the wordmark's red square, in Ink). */
.sheet-initial {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: 0 0 auto;
  width: 28px;
  height: 28px;
  margin-right: 10px;
  background: var(--ink);
  color: var(--paper);
  font-family: var(--display);
  font-size: 14px;
  line-height: 1;
}
.sheet-item-label {
  flex: 1 1 auto;
}

/* RECORD primary action + chooser (AC6). RECORD is the filled `.btn`; the header
   copy shows at phone width only (the sheet copy rides the sheet's visibility).
   The chooser APPEARS from the bottom — no easing. Flat, token-only. */
/* RECORD reuses the filled .btn but must clear the 44px tap-target floor this
   shell enforces on every other control (WCAG AA, AC10). */
.record-btn {
  min-height: 44px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}
.header-record {
  display: none; /* desktop hidden; the <=719px block shows it */
}
.record-chooser {
  position: fixed;
  inset: 0;
  z-index: 60; /* above the sheet */
  display: flex;
  align-items: flex-end;
  justify-content: center;
}
.record-chooser[hidden] {
  display: none;
}
.record-chooser-backdrop {
  position: absolute;
  inset: 0;
  background: var(--ink);
  opacity: 0.4;
}
.record-chooser-panel {
  position: relative;
  width: 100%;
  max-width: 480px;
  background: var(--paper);
  border-top: 1px solid var(--rule);
  display: flex;
  flex-direction: column;
}
.record-chooser-line {
  min-height: 44px;
  padding: 16px;
  text-align: left;
  border: 0;
  border-bottom: 1px solid var(--rule);
  background: var(--paper);
  color: var(--ink);
  font-size: 16px;
  cursor: pointer;
}
.record-chooser-line:hover {
  background: var(--ink);
  color: var(--paper);
}

/* --- Household portal (PRD-0016) -----------------------------------------
   Login-free "WHERE IS TRENT" page. Mobile-first, Timetable design system,
   warmer voice + larger type, flat (no radius/shadow/gradient), WCAG AA. */
.portal {
  max-width: 640px;
  margin: 0 auto;
  padding: 24px 20px 0;
}
.portal-hero {
  border-top: 3px solid var(--ink);
  padding: 20px 0 24px;
}
.portal-hero-inFlight {
  border-top-color: var(--red);
}
.portal-title {
  font-family: var(--display);
  letter-spacing: -0.04em;
  line-height: 0.98;
  font-size: clamp(34px, 9vw, 56px);
  margin: 0;
  color: var(--ink);
}
.portal-sub {
  font-size: clamp(16px, 4.5vw, 20px);
  color: var(--sec);
  margin: 10px 0 0;
}
.portal-block {
  border-top: 2px solid var(--ink);
  padding: 16px 0 20px;
}
.portal-hotel-name {
  font-family: var(--display);
  font-size: clamp(22px, 6vw, 30px);
  margin: 6px 0 0;
  color: var(--ink);
}
.portal-hotel-addr {
  font-size: 17px;
  color: var(--ink);
  margin: 6px 0 0;
}
.portal-hotel-meta {
  font-size: 15px;
  color: var(--sec);
  margin: 8px 0 0;
}
.portal-timeline,
.portal-strip {
  list-style: none;
  margin: 10px 0 0;
  padding: 0;
}
.portal-tl {
  display: flex;
  flex-direction: column;
  padding: 12px 0;
  border-bottom: 1px solid var(--rule);
}
.portal-tl-label {
  font-size: 18px;
  color: var(--ink);
}
.portal-tl-detail {
  font-size: 15px;
  color: var(--sec);
  margin-top: 2px;
}
.portal-tl-night .portal-tl-label {
  font-family: var(--display);
}
.portal-week {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  padding: 12px 0;
  border-bottom: 1px solid var(--rule);
}
.portal-week-label {
  font-size: 18px;
  color: var(--ink);
}
.portal-week-tag {
  font-size: 12px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--sec);
}
.portal-week-travel .portal-week-tag {
  color: var(--red);
}
.portal-foot {
  border-top: 2px solid var(--ink);
  margin-top: 12px;
  padding: 18px 0 40px;
  font-size: 13px;
  color: var(--sec);
}

/* Owner Share panel (PRD-0016 AC6) */
.share-link {
  width: 100%;
  margin: 12px 0;
  font-size: 15px;
}
.share-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
}

/* --- Rate grid (PRD-0017) ------------------------------------------------
   Hotel × week matrix. Sticky hotel column, three-layer cells, banding by
   numeral weight + rules (never colour floods). Flat: no radius/shadow/gradient.
   "no rate seen" is an inline-SVG diagonal hatch (not a gradient, not an image). */
.grid-controls {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: 16px;
  padding: 8px 0 16px;
  border-bottom: 2px solid var(--ink);
}
.grid-control {
  margin-bottom: 0;
}
.grid-check {
  display: inline-flex;
  align-items: center;
  gap: 6px;
}
.grid-num {
  width: 90px;
}
.grid-sort {
  padding: 8px;
  border: 2px solid var(--ink);
  background: var(--paper);
  color: var(--ink);
  font-family: var(--body);
  font-size: 14px;
}
.grid-legend {
  margin: 14px 0 4px;
}
.grid-legend summary {
  cursor: pointer;
}
.grid-legend-body {
  padding: 8px 0 4px;
  font-size: 13px;
  color: var(--ink);
  max-width: 640px;
}
.grid-legend-body ul {
  margin: 6px 0 6px 18px;
}
.grid-legend-body li {
  margin: 4px 0;
}
.hatch-defs {
  position: absolute;
  width: 0;
  height: 0;
}
/* P1: the "no rate seen" hatch stroke is a token, not a hardcoded gray. */
.hatch-line {
  stroke: var(--sec);
}
/* PRD-0020 AC4: the SOLD OUT hatch reuses the same inline-SVG pattern mechanism
   but strokes in Signal-Red, so it reads distinctly from the gray "no rate seen"
   hatch. A CSS var resolves only as a property, so it is set via this class. */
.hatch-line-soldout {
  stroke: var(--red);
}
.grid-scroll {
  overflow-x: auto;
  margin-top: 16px;
}
.grid-table {
  border-collapse: collapse;
  min-width: 100%;
}
.grid-table th,
.grid-table td {
  border-bottom: 1px solid var(--rule);
  border-right: 1px solid var(--rule);
  padding: 8px 10px;
  text-align: left;
  vertical-align: top;
}
.grid-hotel {
  position: sticky;
  left: 0;
  z-index: 1;
  background: var(--paper);
  border-right: 2px solid var(--ink);
  min-width: 160px;
}
.grid-corner {
  z-index: 2;
  border-bottom: 2px solid var(--ink);
}
.grid-colhead {
  border-bottom: 2px solid var(--ink);
  min-width: 120px;
}
.grid-cell {
  min-width: 120px;
}
.grid-week-link {
  font-family: var(--display);
  font-size: 15px;
  letter-spacing: -0.03em;
  text-decoration: none;
}
.grid-hotel-name {
  display: block;
  font-family: var(--display);
  font-size: 15px;
  letter-spacing: -0.02em;
}
.grid-hotel-meta {
  display: block;
  margin-top: 2px;
}
.grid-surge-cause {
  display: block;
  margin-top: 4px;
  color: var(--red);
}
.grid-surge-rec {
  margin-top: 6px;
}
/* Surge weeks: red top rule across the column (numeral + rule, no flood). */
.grid-col-surge {
  border-top: 3px solid var(--red);
}
.gc-layer {
  line-height: 1.25;
}
.gc-refund {
  font-family: var(--display);
  font-size: 16px;
  letter-spacing: -0.02em;
}
.gc-prepaid {
  font-size: 11px;
  color: var(--sec);
  margin-top: 2px;
}
.gc-direct {
  font-size: 11px;
  color: var(--sec);
  margin-top: 2px;
}
.gc-direct.earns {
  color: var(--ink);
}
.gc-indic {
  color: var(--sec);
}
/* Over-budget: a thin Signal-Red underline under the refundable primary. */
.grid-over-budget .gc-refund {
  border-bottom: 2px solid var(--red);
  display: inline-block;
}
/* No rate seen: the inline-SVG hatch fills the cell behind a small label. */
.grid-norate {
  position: relative;
}
.hatch-mark {
  display: block;
  width: 100%;
  height: 18px;
}
.grid-norate-label {
  display: block;
  margin-top: 2px;
}
.grid-soldout {
  position: relative;
}
.grid-soldout-label {
  display: block;
  margin-top: 2px;
  color: var(--red);
}

/* --- Week detail (PRD-0017) ----------------------------------------------
   One week deep. Legs, ranked hotels, watch panel, surge banner, paste box.
   Flat, tokens only; hierarchy is numeral weight + rules. */
.week-block {
  border-top: 2px solid var(--ink);
  padding: 16px 0 20px;
}
.week-surge {
  border-top: 3px solid var(--red);
  padding: 12px 0 16px;
}
.week-surge-title {
  color: var(--red);
}
.week-surge-cause {
  font-size: 15px;
  margin: 4px 0 8px;
}
/* PRD-0024 R5 holding line — display-layer honesty beside the surge banner. Red
   top rule ties it to the surge signal; flat, tokens only. */
.week-holding {
  border-top: 3px solid var(--red);
  padding: 12px 0 16px;
}
.week-holding-title {
  color: var(--red);
}
.week-holding-line {
  font-size: 15px;
  margin: 4px 0 0;
}
.week-leg {
  font-size: 14px;
  padding: 4px 0;
  border-bottom: 1px solid var(--rule);
}
/* PRD-0027 (#80): the record locator (PNR) reads as a code, not prose. Generic
   monospace keyword — no font file, so the self-hosted-fonts flat rule holds. */
.pnr {
  font-family: monospace;
}
.week-hotel {
  padding: 10px 0;
  border-bottom: 1px solid var(--rule);
}
.week-hotel-best {
  border-left: 3px solid var(--red);
  padding-left: 10px;
}
.week-hotel-head {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 10px;
}
.week-hotel-name {
  font-family: var(--display);
  font-size: 16px;
  letter-spacing: -0.02em;
}
.week-hotel-price {
  font-size: 16px;
}
.week-why {
  margin-top: 6px;
}
.week-why summary {
  cursor: pointer;
}
.week-why-body {
  font-size: 13px;
  color: var(--sec);
  padding: 6px 0 2px;
}
.week-watch-state {
  font-size: 15px;
  margin-bottom: 6px;
}
.week-checks {
  list-style: none;
  margin: 6px 0 0;
  padding: 0;
}
.week-check {
  font-size: 13px;
  padding: 4px 0;
  border-bottom: 1px solid var(--rule);
}
.week-watch-form,
.week-paste form {
  margin-top: 10px;
}
/* Cancel-hedge affordance + quote.record form (PRD-0019 AC5) — flat, tokens
   only, reusing .week-block / .field / .btn / .error. */
.rebook-note {
  margin: 6px 0 10px;
  font-weight: 600;
}
/* PRD-0031 R3: the one ruled stay line under the This Week hero. */
.stay-line {
  margin: 4px 0 12px;
  padding-top: 8px;
  border-top: 2px solid var(--rule);
  font-weight: 600;
}
.cancel-hedge-form,
.quote-form {
  margin-top: 10px;
}
.week-paste-area {
  width: 100%;
  padding: 10px;
  border: 2px solid var(--ink);
  background: var(--paper);
  color: var(--ink);
  font-family: var(--body);
  font-size: 14px;
  margin-bottom: 10px;
}

/* ---- alert center (PRD-0018) ----
   Flat, token-only. Hierarchy is numeral/label weight + a left rule, never a
   colour flood: an unread alert gets a Signal-Red left rule + inked text; a
   read one is muted. Kind chips reuse the .chip tones (ok / rd / line). */
.alerts-controls {
  display: flex;
  align-items: center;
  gap: 16px;
  margin: 8px 0 4px;
}
.alerts-list {
  list-style: none;
  margin: 8px 0 0;
  padding: 0;
}
.alerts-row {
  display: block;
  padding: 14px 0 14px 14px;
  border-top: 1px solid var(--rule);
  border-left: 2px solid transparent;
}
.alerts-row.unread {
  border-left-color: var(--red);
}
.alerts-row.read {
  color: var(--sec);
}
.alerts-row-head {
  display: flex;
  align-items: baseline;
  gap: 10px;
  flex-wrap: wrap;
}
.alerts-summary {
  font-size: 16px;
  font-weight: 600;
}
.alerts-row.read .alerts-summary {
  font-weight: 500;
}
.alerts-time {
  font-size: 11px;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--sec);
}
.alerts-detail {
  margin-top: 4px;
  font-size: 14px;
}
.alerts-link {
  display: inline-block;
  margin-top: 6px;
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}
.alerts-ack {
  margin-top: 6px;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  padding: 6px 12px;
  border: 2px solid var(--ink);
  background: var(--paper);
  color: var(--ink);
  cursor: pointer;
}
.alerts-ack:hover {
  background: var(--ink);
  color: var(--paper);
}

/* --- Inbox — the BYO-AI confirm surface (PRD-0028) ------------------------- */
.inbox-list {
  list-style: none;
  margin: 8px 0 0;
  padding: 0;
}
.inbox-row {
  display: block;
  padding: 14px 0 14px 14px;
  border-top: 1px solid var(--rule);
  border-left: 2px solid var(--ink);
}
.inbox-row-head {
  display: flex;
  align-items: baseline;
  gap: 10px;
  flex-wrap: wrap;
}
.inbox-source {
  font-size: 16px;
  font-weight: 600;
  overflow-wrap: anywhere;
}
.inbox-time {
  font-size: 11px;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--sec);
}
.inbox-fields {
  display: grid;
  grid-template-columns: max-content 1fr;
  gap: 2px 14px;
  margin: 8px 0 0;
  font-size: 14px;
}
.inbox-fields dt {
  color: var(--sec);
  font-size: 11px;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}
.inbox-fields dd {
  margin: 0;
  font-family: monospace;
  overflow-wrap: anywhere;
}
.inbox-actions {
  display: flex;
  gap: 10px;
  margin-top: 8px;
}
.inbox-promote,
.inbox-discard,
.inbox-move-confirm {
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  padding: 8px 14px;
  min-height: 44px;
  border: 2px solid var(--ink);
  background: var(--paper);
  color: var(--ink);
  cursor: pointer;
}
.inbox-promote.armed,
.inbox-move-confirm {
  background: var(--red);
  border-color: var(--red);
  color: var(--paper);
}
.inbox-promote:disabled,
.inbox-discard:disabled,
.inbox-move-confirm:disabled {
  opacity: 0.5;
  cursor: default;
}
.inbox-move {
  margin-top: 10px;
  padding: 10px 12px;
  border: 2px solid var(--red);
}
.inbox-move-heading {
  margin: 0 0 4px;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.04em;
  color: var(--red);
}
.inbox-move-desc {
  margin: 0 0 8px;
  font-size: 14px;
}

/* --- Account hub / household invites / settings (PRD-0029) ------------------
   The Main, Invites, and Settings artboards under the LOCKED design system: flat
   (no radius/shadow/gradient), the five tokens only, Archivo Black display, ruled
   rows, ≥44px tap targets on every row/link/button. Copy is literal uppercase
   where the LIVE-DoD greps need it (never CSS text-transform alone). */
.back-link {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  text-decoration: none;
}
.account-name {
  font-size: clamp(36px, 11vw, 44px);
  overflow-wrap: anywhere; /* a long no-space name must not overflow a 375px phone */
  margin-top: 4px;
}
.account-email {
  margin-top: 8px;
}
.account-rows {
  border-top: 2px solid var(--ink);
  margin-top: 24px;
}
.account-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  min-height: 44px;
  padding: 12px 0;
  border-bottom: 1px solid var(--rule);
  text-decoration: none;
  color: var(--ink);
}
.account-row-text,
.set-text {
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.account-row-title,
.set-title {
  font-size: 13px;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}
.account-row-desc,
.set-desc {
  font-size: 13px;
  color: var(--sec);
}
/* The trailing chevron — stroked via a class because a CSS var() never resolves
   as an SVG stroke= attribute (PRD-0019 P1). */
.chevron {
  flex: 0 0 auto;
  stroke: var(--ink);
}
.account-signout {
  width: 100%;
  min-height: 44px;
  margin-top: 32px;
}
.invites-title,
.settings-title {
  font-size: clamp(30px, 9vw, 36px);
  margin: 4px 0 12px;
}
/* Every control on the account-area screens clears the 44px floor — including the
   pre-existing share buttons now that they live on a phone-first screen. */
.invites .btn,
.share-actions .btn {
  min-height: 44px;
}
/* The active-link card (Invites artboard): a 2px Ink border, never a shadow. */
.invite-card {
  border: 2px solid var(--ink);
  padding: 16px;
  margin-top: 24px;
  display: flex;
  flex-direction: column;
  gap: 12px;
}
.invite-card-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
}
.invite-card .share-link,
.invite-card .share-viewed {
  margin: 0;
}
.share-viewed {
  margin: 8px 0 12px;
}
.invite-card + .label {
  margin-top: 12px;
}
/* Revoke reads in Signal Red — a token, never a colour flood (F9 keeps it two-step).
   Selector specificity must beat `.btn.line` (0,2,0), which sets color/border too. */
.btn.line.share-revoke {
  color: var(--red);
  border-color: var(--red);
  outline-color: var(--red);
}
.btn.line.share-revoke:hover {
  background: var(--red);
  color: var(--paper);
}
/* Settings groups + rows (only-real-switches: a display-only row is a plain div). */
.set-group {
  border-top: 2px solid var(--ink);
  margin-top: 16px;
}
.set-group-label {
  margin: 10px 0 0;
}
.setrow {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  min-height: 44px;
  width: 100%;
  padding: 8px 0;
  border: 0;
  border-bottom: 1px solid var(--rule);
  background: var(--paper);
  color: var(--ink);
  font-family: var(--body);
  font-size: 15px;
  text-align: left;
  text-decoration: none;
  cursor: default;
}
a.setrow,
button.setrow {
  cursor: pointer;
}
.signout-caption {
  margin-top: 6px;
}

/* --- Inbound address + NEEDS YOUR AI (PRD-0032) ----------------------------
   The forward-a-confirmation lane, under the LOCKED design system: flat (no
   radius, no shadow, no gradient), the five tokens only, ruled blocks, >=44px tap
   targets. The address and the mail excerpt are monospace via the generic keyword
   (the `.pnr` idiom) — no external font origin. */
.inbound-title {
  font-size: clamp(30px, 9vw, 36px);
  margin: 4px 0 12px;
}
.inbound-card {
  border: 2px solid var(--ink);
  padding: 16px;
  margin-top: 24px;
  display: flex;
  flex-direction: column;
  gap: 12px;
}
.inbound-card-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
}
/* The secret address: monospace so every hex character is distinguishable, and
   `overflow-wrap: anywhere` so a 32-char local part cannot overflow a 375px phone. */
.inbound-address {
  margin: 0;
  font-family: monospace;
  font-size: 15px;
  overflow-wrap: anywhere;
}
.inbound-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
}
.inbound-actions .btn,
.inbound-create,
.inbound-save-senders {
  min-height: 44px;
}
.inbound-create {
  margin-top: 24px;
}
.inbound-senders {
  border-top: 2px solid var(--ink);
  margin-top: 24px;
  padding-top: 12px;
}
.inbound-senders-list {
  list-style: none;
  margin: 6px 0 12px;
  padding: 0;
  font-family: monospace;
  font-size: 14px;
  overflow-wrap: anywhere;
}
.inbound-senders-list li {
  padding: 6px 0;
  border-bottom: 1px solid var(--rule);
}
/* Nothing registered means nothing can reach the lane — the honest rail reads red. */
.inbound-senders-warning {
  margin: 6px 0 12px;
  color: var(--red);
}
.inbound-senders-form {
  margin-top: 8px;
}
.inbound-note {
  margin-top: 16px;
}

/* NEEDS YOUR AI — unreadable forwarded mail, above the pending drafts. The
   Signal-Red left rule marks it as the section that nothing else will pick up. */
.needs-ai {
  margin: 8px 0 24px;
  padding-left: 14px;
  border-left: 2px solid var(--red);
}
.needs-ai-heading {
  margin: 0;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--red);
}
.needs-ai-copy {
  margin: 4px 0 0;
  font-size: 13px;
  color: var(--sec);
}
.needs-ai-list {
  list-style: none;
  margin: 8px 0 0;
  padding: 0;
}
.needs-ai-row {
  padding: 12px 0;
  border-top: 1px solid var(--rule);
}
/* The lane's own explanation of what it did and did not do. */
.needs-ai-note {
  margin: 6px 0 0;
  font-size: 13px;
  line-height: 1.4;
  color: var(--ink);
}
.needs-ai-excerpt {
  margin: 8px 0 0;
  padding: 10px;
  max-height: 200px;
  overflow: auto;
  border: 1px solid var(--rule);
  background: var(--paper);
  color: var(--ink);
  font-family: monospace;
  font-size: 13px;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}
.needs-ai-copy-btn {
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  padding: 8px 14px;
  min-height: 44px;
  border: 2px solid var(--ink);
  background: var(--paper);
  color: var(--ink);
  cursor: pointer;
}
.needs-ai-copy-btn:hover {
  background: var(--ink);
  color: var(--paper);
}
.inbox-mail-note {
  margin-bottom: 8px;
}

/* ---- PRD-0034 S3: WEEKS = HOLDING · MARKET · MOVE ----------------------
   The twelve rows as the founder reads them. Flat, tokens only: hierarchy is
   numeral weight + rules; the one red mark is the missing cancel-by. */
.holding-line {
  display: block;
}
.holding-meta {
  display: block;
  font-size: 12px;
  color: var(--sec);
  margin-top: 2px;
}
.holding-missing {
  color: var(--red);
  font-weight: 600;
}
.market-delta {
  font-family: var(--display);
  letter-spacing: -0.03em;
  margin-left: 6px;
}
.market-delta.down {
  color: var(--red);
}
.move-link {
  text-decoration: none;
}
.move-link.chip.rd:hover,
.move-link.chip.line:hover {
  text-decoration: underline;
}

/* ---- PRD-0034 S3: the week spine ------------------------------------------
   Back link, a horizontally scrollable strip of twelve chips (the current one
   filled), prev/next at both ends. On a phone the strip scrolls; nothing wraps. */
.week-back {
  display: inline-block;
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  text-decoration: none;
  margin-bottom: 8px;
}
.week-strip {
  display: flex;
  align-items: center;
  gap: 6px;
  overflow-x: auto;
  padding: 4px 0 10px;
  border-bottom: 2px solid var(--ink);
  margin-bottom: 12px;
  -webkit-overflow-scrolling: touch;
}
.week-chip {
  flex: 0 0 auto;
  font-family: var(--display);
  font-size: 13px;
  letter-spacing: -0.02em;
  text-decoration: none;
  padding: 6px 8px;
  border: 2px solid var(--ink);
  color: var(--ink);
  background: var(--paper);
  min-height: 32px;
}
.week-chip.current {
  background: var(--ink);
  color: var(--paper);
}
.week-chip.notravel {
  border-color: var(--rule);
  color: var(--sec);
}
.week-nav {
  flex: 0 0 auto;
  font-family: var(--display);
  font-size: 15px;
  text-decoration: none;
  padding: 6px 8px;
  color: var(--ink);
}
.week-nav[aria-disabled="true"] {
  color: var(--rule);
  pointer-events: none;
}
.week-actions {
  border-top: 2px solid var(--ink);
  padding: 12px 0 0;
}
.week-actions > summary {
  cursor: pointer;
  list-style: none;
}
.week-actions > summary::-webkit-details-marker {
  display: none;
}

/* ---- PRD-0034 S3: grid sort-by-week -------------------------------------- */
.grid-sort-week {
  display: inline-block;
  margin-left: 6px;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.06em;
  padding: 2px 6px;
  border: 2px solid var(--ink);
  background: var(--paper);
  color: var(--ink);
  cursor: pointer;
}
th[aria-sort="ascending"] .grid-sort-week {
  background: var(--ink);
  color: var(--paper);
}

/* ---- PRD-0034 S4: NEEDS YOU + the alerts log ------------------------------
   The desktop ALERTS link carries the one badge (needs-you count); the
   excerpt folds to a line with SHOW; DISMISS is the primary control. */
.navlink-alerts {
  display: inline-flex;
  align-items: center;
  gap: 6px;
}
.needs-ai-reason {
  font-size: 13px;
  margin: 4px 0;
}
.needs-ai-excerpt.folded {
  max-height: 3.2em;
  overflow: hidden;
}
.needs-ai-show {
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  background: none;
  border: 0;
  padding: 0;
  color: var(--ink);
  text-decoration: underline;
  cursor: pointer;
  min-height: 44px;
}
.needs-ai-dismiss {
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  padding: 10px 14px;
  min-height: 44px;
  background: var(--ink);
  color: var(--paper);
  border: 2px solid var(--ink);
  cursor: pointer;
}
.needs-ai-dismiss:disabled {
  opacity: 0.5;
  cursor: default;
}
.needs-ai-copy-btn.secondary {
  background: var(--paper);
  color: var(--ink);
}
.alerts-ack-all {
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  padding: 10px 14px;
  min-height: 44px;
  background: var(--paper);
  color: var(--ink);
  border: 2px solid var(--ink);
  cursor: pointer;
  margin-left: auto;
}
.alerts-ack-all:disabled {
  opacity: 0.5;
  cursor: default;
}

/* PRD-0034 R6 — Bookings: the red cancel-by mark, the inline edit, the row cancel block. */
.cancel-by-missing {
  color: var(--red);
  font-weight: 600;
}
.booking-actions .btn {
  margin-right: 6px;
  padding: 6px 10px;
  font-size: 12px;
}
.booking-edit-input {
  width: 100%;
  padding: 6px;
  border: 2px solid var(--ink);
  background: var(--paper);
  color: var(--ink);
  font-family: var(--body);
  font-size: 14px;
}
.booking-cancel-row td {
  padding: 0 0 12px;
}
/* PRD-0034 R9 — HOW THIS MOVES under the gate tile. */
.how-this-moves {
  margin: 16px 0;
  padding-left: 12px;
  border-left: 3px solid var(--red);
}
.move-line {
  margin: 6px 0;
  font-weight: 600;
}
.move-none {
  font-weight: 400;
}
.move-market,
.move-constant,
.cat-suffix {
  opacity: 0.7;
}
