/* ═══════════════════════════════════════════════════════════════
   XODE — RESPONSIVE LAYER

   Loaded last on every page, so it has the final say.

   Two things were wrong before this file existed:

   1. The breakpoints in shared.css run smallest-first (479 → 767 →
      1023). Because they are all max-width queries, every one of them
      matches on a phone — and the LAST one wins. So a 375px screen was
      being styled by the 1023px rules: the footer stayed two columns
      and spilled 8px off the right edge, hidden only by an
      overflow-x: hidden on <body>.

   2. There was nothing above 1280px and nothing below 479px, so the
      site was cramped on a 27" monitor and broken on a folded phone.

   The blocks here run largest-first, so a narrower screen always gets
   the last word. Ranged queries (min-width AND max-width) are used
   wherever a rule should apply to one band only.
   ═══════════════════════════════════════════════════════════════ */

/* ─────────────────────────────────────────────────────────────
   0. FOUNDATIONS — every screen
   ───────────────────────────────────────────────────────────── */

/* Fluid type: one curve from a folded phone to a 4K monitor, instead
   of two hard jumps. */
:root {
  --fluid-h1: clamp(2rem, 1.1rem + 4.4vw, 4.25rem);
  --fluid-h2: clamp(1.65rem, 1rem + 2.9vw, 3rem);
  --fluid-h3: clamp(1.2rem, .95rem + 1.1vw, 1.6rem);
  --fluid-lead: clamp(.95rem, .88rem + .38vw, 1.15rem);
  --gutter: clamp(16px, 4vw, 40px);
}

/* Nothing may push the page sideways. The hidden overflow stays as a
   backstop, but the layout below no longer relies on it.

   IT GOES ON body AND NOT ON html, and that is not a style choice.
   The root element's overflow is handed to the viewport, and body's
   is handed over only while the root's is still visible. Put
   overflow-x: hidden on html and body stops handing anything over —
   it becomes a scroll container itself, one viewport tall, and the
   whole page scrolls INSIDE it rather than in the viewport. Three
   things break the moment that happens:

     window.scrollTo and window.pageYOffset go dead — they address
     the viewport, which no longer scrolls;
     scroll-behavior: smooth on html has nothing to smooth;
     and the scrollbar becomes body's own, drawn down the inside
     edge of a box that starts at y=0 — so it runs up behind the
     fixed header and out the other side.

   That last one is what it looked like from the outside: a scrollbar
   hiding inside the header. */
body { overflow-x: hidden; max-width: 100%; }

/* And the other half of the same bug. styles.css opens with
       html, body { height: 100%; ... }
   which is right for the editor — an application shell that fills the
   window and scrolls its own panels — and wrong for a marketing page,
   because it pins body to one viewport tall. A body that is 910px tall
   holding 11,500px of page has to scroll itself, and a box that scrolls
   itself does not hand the job to the viewport.

   So the pages that are documents take it back. This sheet is loaded by
   all 23 of them and by none of the editors, which is exactly the line
   the rule needs to fall on. min-height keeps the full-height background
   on a page too short to fill the window. */
html, body { height: auto; min-height: 100%; }

/* Long unbroken strings — URLs, slugs, emails — are the usual cause of
   a stray horizontal scrollbar on a phone. */
p, li, dd, td, .caption, .footer-desc, .publish-live-url, .rv-text {
  overflow-wrap: break-word;
  word-break: break-word;
}

/* Media never dictates layout width. */
img, svg, video, canvas, iframe, embed, object { max-width: 100%; }
img, video { height: auto; }

/* Code blocks scroll rather than stretch the page. Tables are left
   alone on purpose: display:block on a <table> throws away column
   alignment, and the wide ones here (the admin grid) already sit in
   their own scrolling wrapper. */
pre { max-width: 100%; overflow-x: auto; }
.grid-scroll, .table-scroll { max-width: 100%; overflow-x: auto; -webkit-overflow-scrolling: touch; }

/* Notched and rounded screens. Applied to the inner containers rather
   than <body>, so full-bleed section backgrounds still reach the edge
   while the text they hold clears the cutout. */
@supports (padding: max(0px)) {
  .container, .nav-inner {
    padding-left: max(var(--gutter, 20px), env(safe-area-inset-left));
    padding-right: max(var(--gutter, 20px), env(safe-area-inset-right));
  }
  footer, .site-footer { padding-bottom: max(0px, env(safe-area-inset-bottom)); }
}

/* ─────────────────────────────────────────────────────────────
   1. ULTRA-WIDE — 1800px and up
   Content pinned to a readable measure looks abandoned on a 27"
   monitor; give it room without letting lines run long.
   ───────────────────────────────────────────────────────────── */
@media (min-width: 1800px) {
  :root { --max-w: 1560px; }
  html { font-size: 17px; }
  .hero-inner { gap: 72px; }
}

@media (min-width: 2400px) {
  :root { --max-w: 1720px; }
  html { font-size: 18px; }
}

/* ─────────────────────────────────────────────────────────────
   2. LARGE DESKTOP — 1440–1799px
   ───────────────────────────────────────────────────────────── */
@media (min-width: 1440px) and (max-width: 1799px) {
  :root { --max-w: 1320px; }
}

/* ─────────────────────────────────────────────────────────────
   3. SMALL LAPTOP — 1024–1279px
   The band that was falling between the desktop and tablet rules.
   ───────────────────────────────────────────────────────────── */
@media (min-width: 1024px) and (max-width: 1279px) {
  .container { padding: 0 32px; }
  .prof-grid { grid-template-columns: repeat(3, 1fr); }
  .topic-grid { grid-template-columns: repeat(3, 1fr); }
  .gw-grid { grid-template-columns: repeat(3, 1fr); }
}

/* ─────────────────────────────────────────────────────────────
   4. TABLET — 768–1023px
   ───────────────────────────────────────────────────────────── */
@media (max-width: 1023px) {
  .container { padding: 0 var(--gutter); }
  section { padding: clamp(48px, 7vw, 80px) 0; }
  .footer-grid { grid-template-columns: repeat(2, 1fr); gap: 32px; }
  .prof-grid, .topic-grid { grid-template-columns: repeat(2, 1fr); }
  .why-hire-grid { grid-template-columns: repeat(2, 1fr); }
  .counter-grid { grid-template-columns: repeat(2, 1fr); }
  .gw-grid { grid-template-columns: repeat(2, 1fr); }
}

/* ─────────────────────────────────────────────────────────────
   5. PHONE AND SMALL TABLET — ≤767px
   ───────────────────────────────────────────────────────────── */
@media (max-width: 767px) {
  h1, .hero-title { font-size: var(--fluid-h1); line-height: 1.08; }
  h2, .sec-title  { font-size: var(--fluid-h2); line-height: 1.14; }
  h3              { font-size: var(--fluid-h3); }
  .hero-sub, .sec-sub, .lead { font-size: var(--fluid-lead); }

  .nav-links { display: none; }
  section { padding: clamp(40px, 9vw, 64px) 0; }

  /* One column, for real this time. */
  .footer-grid { grid-template-columns: 1fr 1fr; gap: 26px; }
  .story-grid, .pitch-grid, .why-grid, .why-hire-grid,
  .team-grid, .contact-grid, .testi-grid,
  .hero-inner, .name-row { grid-template-columns: 1fr !important; }

  .prof-grid, .topic-grid, .counter-grid, .gw-grid, .gw-strip {
    grid-template-columns: repeat(2, 1fr);
  }

  .hero-visual, .story-visual { display: none; }
  .newsletter-form { flex-direction: column; align-items: stretch; }
  .newsletter-btn { width: 100%; justify-content: center; }
}

/* ─────────────────────────────────────────────────────────────
   6. PHONE — ≤560px
   Below this a two-column grid stops being a grid and starts being
   two narrow columns of clipped text.
   ───────────────────────────────────────────────────────────── */
@media (max-width: 560px) {
  .footer-grid { grid-template-columns: 1fr; gap: 30px; }
  .prof-grid, .topic-grid, .counter-grid,
  .gw-grid, .gw-strip, .feat-inner { grid-template-columns: 1fr; }

  .feat-item { flex: 1 1 100%; border-right: none; }
  .about-hero-stats, .hero-stats { flex-direction: column; align-items: flex-start; gap: 16px; }
  .collab-logo-item { flex: 1 1 100%; border-right: none; }

  /* Call-to-action buttons stop sitting shoulder to shoulder and go
     full width. Scoped to the places where that is what you want — a
     blanket rule would stretch the nav CTA across the header. */
  .hero-actions > .btn-primary, .hero-actions > .btn-ghost, .hero-actions > .btn-amber,
  .cta-actions > .btn-primary, .cta-actions > .btn-ghost, .cta-actions > .btn-amber,
  .cta-banner .btn-xl,
  .btn-xl, .btn-lg {
    width: 100%;
    justify-content: center;
  }
  .btn-row, .hero-actions, .cta-actions {
    flex-direction: column;
    align-items: stretch;
    gap: 10px;
  }
  /* Never the nav CTA, and never a genuine pair of small chips. */
  .nav-cta, .btn-row-2 .btn-primary, .btn-row-2 .btn-ghost { width: auto; }
  .btn-row-2 { flex-direction: row; }
}

/* ─────────────────────────────────────────────────────────────
   7. NARROW PHONE / FOLDED — ≤380px
   ───────────────────────────────────────────────────────────── */
@media (max-width: 380px) {
  .container { padding: 0 14px; }
  .nav-inner { padding: 0 14px; }
  /* Only the offset here. The min-width this used to set forced the
     panel to 300px on a 375px screen, overriding the width set
     further down — min-width always wins over width. */
  .hamburger-panel { right: -2px; }
  .nav-cta { padding: 7px 10px; font-size: 11.5px; }
  section { padding: 36px 0; }
}

/* Galaxy Fold closed, split-screen multitasking, car displays. */
@media (max-width: 320px) {
  html { font-size: 13.5px; }
  .container { padding: 0 10px; }
  .nav-logo-text, .footer-logo-text { font-size: 20px; }
}

/* ─────────────────────────────────────────────────────────────
   8. PHONE IN LANDSCAPE — short viewports
   Full-height heroes are unreadable when the viewport is 380px tall.
   ───────────────────────────────────────────────────────────── */
@media (max-height: 520px) and (orientation: landscape) {
  .hero, .hero-section { min-height: auto; padding: 44px 0; }
  section { padding: 40px 0; }
  .hamburger-panel { max-height: 84dvh; }
  .modal, .modal-card { max-height: 92dvh; overflow-y: auto; }
}

/* ─────────────────────────────────────────────────────────────
   9. TOUCH — sized by input device, not screen width
   A 13" touchscreen laptop needs the same targets as a phone.
   ───────────────────────────────────────────────────────────── */
/* Applied on a coarse pointer at any width, and on any narrow screen
   regardless of pointer — a desktop browser at phone width should not
   get finger-sized controls, but it should not get 7px ones either. */
@media (pointer: coarse), (max-width: 640px) {
  /* WCAG asks for 44px; 40 is the practical floor for dense UI. */
  button, .btn-primary, .btn-ghost, .btn-amber,
  .nav-cta, .gw-chip, .rv-tab, .sheet-toggle,
  input[type="submit"], input[type="button"] {
    min-height: 40px;
  }
  .hamburger-btn { min-width: 40px; min-height: 40px; }
  .nav-link, .hamburger-link, .hpanel-link { min-height: 42px; display: flex; align-items: center; }
  .footer-links a { padding: 6px 0; display: inline-block; }

  /* The star rating is the smallest thing anyone has to hit accurately. */
  .rv-rate-btn { min-width: 40px; min-height: 40px; font-size: 22px; }

  /* Carousel dots were 7px tall — a decoration, not a target. Grow the
     hit area with padding and keep the visible dot its original size by
     painting only the content box. */
  .gw-dot, .counter-dot, .dot-nav button {
    min-height: 34px;
    min-width: 34px;
    padding: 13px 4px;
    background-clip: content-box;
    box-sizing: border-box;
  }

  /* Hover-only affordances never fire on touch, so pin them on. */
  .gw-card .gw-overlay,
  .prof-card .prof-hover { opacity: 1; }
}

/* ─────────────────────────────────────────────────────────────
   10. USER PREFERENCES
   ───────────────────────────────────────────────────────────── */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
    scroll-behavior: auto !important;
  }
}

/* Anyone who has zoomed the browser to 200% lands here; treat it like
   a small screen rather than letting the desktop grid hold. */
@media (max-width: 767px) {
  .hamburger-panel { max-height: min(78dvh, 620px); overflow-y: auto; }
}

/* ─────────────────────────────────────────────────────────────
   11. PAGE-LOCAL OVERRIDES
   about.html, contact.html and account.html each carry a <style>
   block in the document head. Those come after this file, so a plain
   class selector here loses to them — these rules carry an extra
   class to win the cascade honestly rather than with !important.
   ───────────────────────────────────────────────────────────── */

/* The numbered process list keeps a 60px number column and two 32px
   gaps whatever the width, so below ~360px the row's min-content width
   exceeded the screen and pushed the page sideways. Let the copy drop
   to its own line instead. */
@media (max-width: 560px) {
  .process-steps .process-step {
    flex-wrap: wrap;
    gap: 12px 14px;
    min-width: 0;
    padding: 24px 0;
  }
  .process-steps .step-num {
    width: auto;
    text-align: left;
    font-size: 34px;
  }
  .process-steps .step-content {
    flex: 1 1 100%;
    min-width: 0;
  }
}

/* Anything laid out as a flex or grid track needs an explicit floor,
   or its longest word sets the page width. */
@media (max-width: 767px) {
  .process-steps,
  .process-step,
  .step-content,
  .contact-grid > *,
  .team-grid > *,
  .acct-grid > *,
  .story-grid > * { min-width: 0; }
}

/* The review filter tabs (Newest / Highly rated / Lowest) are a fixed
   three-across row; below ~300px they run past the edge. Let them
   wrap rather than clip. */
@media (max-width: 400px) {
  .rv-tabs {
    flex-wrap: wrap;
    justify-content: center;
    gap: 6px;
    max-width: 100%;
  }
  .rv-tab { flex: 0 1 auto; }
}

/* ═══════════════════════════════════════════════════════════════
   NAV BAR BREATHING ROOM — phones

   Signed in, the top bar carried five things across a 375px screen:
   logo, search, "Open Editor", the account chip with a first name and
   a portfolio count, and the hamburger. They summed to 338px inside
   347px of usable width — nine pixels of slack shared between four
   gaps — so nothing had any air around it and the hamburger was
   pushed past the right edge.

   Nothing is removed here. The account chip sheds the parts that are
   also shown elsewhere: the count is on the account page, and the full
   name is in the hamburger menu two taps away. The avatar keeps its
   tap target and still links to the account.
   ═══════════════════════════════════════════════════════════════ */

@media (max-width: 640px) {
  .nav-inner {
    gap: 10px;
    padding: 0 14px;
  }

  /* The count means nothing at a glance and costs a whole word of
     width. It stays on the account page where it is read properly. */
  .xode-badge-count { display: none !important; }

  .xode-badge-link {
    padding: 4px 10px 4px 4px !important;
    gap: 7px !important;
  }

  .nav-cta {
    padding: 8px 12px;
    font-size: 12px;
    white-space: nowrap;
  }
  /* The arrow is decoration next to a label that already says where it
     goes, and it is the cheapest thing on the bar to drop. */
  .nav-cta svg { display: none; }
}

/* Below this the first name has to go too — the avatar carries the
   same meaning, and the menu spells it out. */
@media (max-width: 460px) {
  .nav-inner { gap: 8px; padding: 0 12px; }

  .xode-badge-name { display: none !important; }
  .xode-badge-link { padding: 4px !important; border-radius: 100px !important; }

  /* Keep a comfortable target even though the label is gone. */
  .xode-badge-avatar { width: 30px !important; height: 30px !important; }

  .nav-logo img.xode-mark-nav { width: 34px; height: 34px; }
  .nav-search-btn { min-width: 38px; }
}

/* One-handed phones: the editor link becomes the icon it already
   carries, so all five controls fit with space between them. */
@media (max-width: 400px) {
  .nav-inner { gap: 7px; padding: 0 10px; }
  .nav-cta { padding: 8px 11px; font-size: 11.5px; }
}

/* ═══════════════════════════════════════════════════════════════
   PHONES — COMPACT CONTAINERS

   Measured at 375px before this block: the homepage was 15,254px
   tall, about nineteen screens. Almost all of it came from grids
   collapsing to a single column, so eight profession cards became
   eight full-width rows, and the footer's four link lists became one
   very long list.

   Nothing here changes a desktop layout — every rule is inside a
   phone breakpoint, and the rules it overrides are the earlier
   single-column collapses in this same file.
   ═══════════════════════════════════════════════════════════════ */

@media (max-width: 640px) {

  /* ── Hero stats: a row, not a stack ──────────────────────────
     Three short figures side by side read fine at this width and
     save roughly 150px of scroll before the fold. */
  .hero-stats,
  .about-hero-stats {
    flex-direction: row !important;
    align-items: flex-start !important;
    justify-content: space-between;
    gap: 10px !important;
    padding-top: 22px;
    flex-wrap: nowrap;
  }
  .hero-stats > div,
  .about-hero-stats > div { flex: 1 1 0; min-width: 0; }
  .hero-stats .stat-num { font-size: 24px; line-height: 1.15; }
  .hero-stats .stat-lbl {
    font-size: 10.5px;
    line-height: 1.35;
    color: var(--text-3);
  }

  /* ── Profession cards: two up ────────────────────────────────
     Eight cards in one column was 1,500px. Two columns with a
     tighter card halves it, and the caption is the first thing to
     go — the name and icon already say what the card is. */
  .prof-grid,
  .topic-grid {
    grid-template-columns: repeat(2, 1fr) !important;
    gap: 10px !important;
  }
  .prof-card {
    padding: 14px 12px !important;
    border-radius: var(--r-md);
  }
  .prof-icon {
    width: 34px !important; height: 34px !important;
    border-radius: 9px;
    margin-bottom: 9px;
  }
  .prof-icon svg { width: 17px !important; height: 17px !important; }
  .prof-name { font-size: 13px !important; margin-bottom: 3px; }
  .prof-caption {
    font-size: 10.5px !important;
    line-height: 1.4;
    /* Two lines, then ellipsis — a card that grows to fit its
       caption breaks the grid's rhythm. */
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
  }

  /* ── Counters: two up, no dividers ───────────────────────────── */
  .counter-grid {
    grid-template-columns: repeat(2, 1fr) !important;
    gap: 18px 10px !important;
  }
  .c-item {
    padding: 0 4px !important;
    border-right: none !important;
  }
  .c-num { font-size: 30px !important; }
  .c-lbl { font-size: 11.5px !important; line-height: 1.35; }
  .c-caption { font-size: 10px !important; }

  /* ── Testimonials: one column, but a much tighter card ───────── */
  .testi-card {
    padding: 16px 15px !important;
    border-radius: var(--r-md);
  }
  .testi-av { width: 34px !important; height: 34px !important; font-size: 14px !important; }
  .testi-name { font-size: 13px !important; }
  .testi-role-cap { font-size: 10.5px !important; }
  .testi-body { font-size: 13px !important; line-height: 1.6 !important; margin: 10px 0 !important; }
  .stars { font-size: 12px !important; }
  .testi-tag-cap { font-size: 10px !important; padding: 4px 10px !important; }

  /* ── Footer: link lists side by side ─────────────────────────
     One column made a 1,382px footer. The brand block stays full
     width; the link columns pair up beneath it. */
  footer .footer-grid {
    /* minmax(0,1fr) rather than 1fr: a plain 1fr floors at the
       content's own width, so the column with the longest link
       ('Terms & Conditions') grew and left the other narrow. */
    grid-template-columns: repeat(2, minmax(0, 1fr)) !important;
    gap: 24px 16px !important;
  }
  footer .footer-grid > *:first-child { grid-column: 1 / -1; }

  .footer-col-title { font-size: 10.5px; margin-bottom: 10px; }
  .footer-links a {
    padding: 3px 0 !important;
    font-size: 12.5px;
    line-height: 1.5;
  }
  .footer-links li { margin-bottom: 2px; }
  .footer-desc { font-size: 12.5px; line-height: 1.6; }
  .footer-caption { font-size: 11px; }
  .footer-social { width: 32px; height: 32px; }
  .footer-social svg { width: 15px; height: 15px; }
}

/* Narrow phones: the two-up grids stay, everything just tightens. */
@media (max-width: 380px) {
  .prof-grid, .topic-grid { gap: 8px !important; }
  .prof-card { padding: 12px 10px !important; }
  .prof-caption { -webkit-line-clamp: 2; font-size: 10px !important; }
  .hero-stats .stat-num { font-size: 21px; }
  .hero-stats .stat-lbl { font-size: 9.5px; }
  .c-num { font-size: 26px !important; }
  footer .footer-grid { gap: 20px 12px !important; }
}

/* ═══════════════════════════════════════════════════════════════
   PHONES — SECTION INTROS AND TESTIMONIAL CARDS

   The clutter here was not spacing, it was legibility. Section
   captions render at 13px, italic, in --text-3 (#5C5F6B ≈ 3:1
   against the panel — under the 4.5:1 needed for body text), with
   1.9 line-height. Small, dim, slanted and loosely led all at once,
   centred, running the full width of the screen: the eye has
   nothing to hold on to and it reads as noise.

   So this lightens the colour, tightens the leading, and caps the
   measure so lines break at a natural length instead of edge to
   edge. The italic stays — it is the site's caption voice.

   Phone widths only. Desktop keeps its own values.
   ═══════════════════════════════════════════════════════════════ */

@media (max-width: 640px) {

  /* ── Section intros ─────────────────────────────────────────── */
  .section-intro { margin-bottom: 30px !important; }

  .eyebrow,
  .eyebrow-center {
    margin-bottom: 12px !important;
    letter-spacing: 2px;
  }

  .sec-title { line-height: 1.2 !important; }

  .sec-caption {
    font-size: 13.5px !important;
    /* 1.9 was too airy for a two-line caption — the lines drifted
       apart and stopped reading as one sentence. */
    line-height: 1.58 !important;
    color: var(--text-2) !important;
    /* ~34 characters a line, so it wraps where a reader expects. */
    max-width: 30ch;
    margin-left: auto !important;
    margin-right: auto !important;
    margin-top: 12px !important;
    text-wrap: pretty;
  }
  /* Left-aligned sections (the pitch block) keep their alignment —
     only centred intros get centred measure. */
  .pitch-grid .sec-caption,
  .pitch-bg .sec-caption {
    margin-left: 0 !important;
    max-width: 34ch;
  }

  /* ── Testimonial cards ──────────────────────────────────────── */
  .testi-grid { gap: 14px !important; }

  .testi-card {
    /* 15px of side padding left the quote almost touching the
       border. A little more air costs 6px a card. */
    padding: 18px 17px !important;
  }
  .testi-hd { margin-bottom: 12px !important; gap: 11px !important; }
  .testi-name { line-height: 1.3; }
  .testi-role-cap { line-height: 1.4; margin-top: 1px; }

  .stars { margin-bottom: 10px !important; letter-spacing: 1px; }

  .testi-body {
    font-size: 13.5px !important;
    line-height: 1.68 !important;
    margin: 0 0 14px !important;
    color: var(--text-1) !important;
    text-wrap: pretty;
  }
  .testi-tag-cap { margin-top: 0 !important; }

  /* The decorative quote mark sits behind the text at this width and
     muddies the first line. */
  .testi-card::before,
  .testi-card::after { opacity: .35; }

  /* ── Pitch block ────────────────────────────────────────────── */
  .check-list { margin: 22px 0 30px !important; gap: 14px !important; }
  .check-list li { line-height: 1.55; }
}

/* 360, not 380: an iPhone at 375 has room for the fuller padding,
   and pulling it back there undid the breathing space this block was
   added to create. This is for genuinely narrow screens. */
@media (max-width: 360px) {
  .sec-caption { font-size: 13px !important; max-width: 28ch; }
  .testi-card { padding: 16px 15px !important; }
  .testi-body { font-size: 13px !important; }
}

/* ═══════════════════════════════════════════════════════════════
   HAMBURGER MENU — SIZE

   Measured at 375×812 before this block: the panel came to 291×601,
   or 78% of the width and 74% of the height, and still had to scroll.
   Two of the descriptions wrapped onto a second line, which pushed
   those rows to 59px each.

   Everything below is proportion, not a redesign — the same rows,
   icons and wording, drawn smaller. Sizes are written with min() and
   clamp() so the panel tracks the window continuously rather than
   stepping at a breakpoint.
   ═══════════════════════════════════════════════════════════════ */

/* Width follows the window at every size, with a ceiling so it never
   sprawls on a tablet and a floor so it stays usable on a small
   phone. Replaces the fixed 240px minimum. */
.hamburger-panel {
  min-width: 0;
  /* 15rem ≈ 240px. It was 20rem, which is a panel wide enough to read
     as a sidebar rather than a menu. */
  /* px, not rem. The root font-size drops to 14px on phones, so a
     rem width shrank the panel there as a side effect rather than a
     decision — it came out 210px against 233px on a desktop. */
  width: min(240px, calc(100vw - 24px));

  /* Leave the nav bar and a margin below, whatever the browser chrome
     is doing. dvh tracks it as the address bar hides. */
  max-height: min(66dvh, calc(100dvh - 108px));
}

@media (max-width: 640px) {
  .hamburger-panel {
    /* Same 240px as the desktop. At 17.5rem this covered about three
       quarters of a 375px screen, which is why it felt like a sheet
       and not a dropdown. */
    width: min(232px, calc(100vw - 28px));
    max-height: min(62dvh, calc(100dvh - 112px));
    padding: 6px;
    border-radius: var(--r-md);
  }

  /* 59px a row was mostly padding and a wrapped second line. */
  .hpanel-link {
    padding: 7px 9px;
    gap: 9px;
    border-radius: var(--r-sm);
  }
  .hpanel-link-icon { width: 26px; height: 26px; border-radius: 7px; }
  .hpanel-link-icon svg { width: 13px; height: 13px; }
  .hpanel-link-name { font-size: 12.5px; line-height: 1.3; }

  /* One line, then ellipsis. The descriptions are a helpful hint, not
     something anyone reads twice — letting them wrap cost more height
     than the whole row was worth. */
  .hpanel-link-desc {
    font-size: 9.5px;
    line-height: 1.35;
    margin-top: 0;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
  }

  .hpanel-label { padding: 6px 8px 3px; font-size: 9px; letter-spacing: .09em; }
  .hpanel-divider { margin: 4px 0; }
  .hpanel-link.featured { margin: 3px 0; }
}

/* Genuinely narrow screens only. At 400px this also caught 375 and
   390 — the commonest phone widths — and stripped the descriptions
   from the menu most people would see. They fit on one line there
   now, and they are most of what gives the panel its character. */
@media (max-width: 360px) {
  .hamburger-panel { width: min(208px, calc(100vw - 20px)); }
  .hpanel-link-desc { display: none; }
  .hpanel-link { padding: 8px 9px; }
  .hpanel-link-icon { width: 24px; height: 24px; }
  .hpanel-link-icon svg { width: 12px; height: 12px; }
}

/* Landscape on a phone: almost no height to work with, so the panel
   becomes a short scrolling list rather than a full-height sheet. */
@media (max-height: 480px) {
  .hamburger-panel { max-height: calc(100dvh - 76px); }
  .hpanel-link { padding: 6px 9px; }
  .hpanel-link-desc { display: none; }
}
