/* ============================================================
   Data Dungeon — DESKTOP layout layer.

   EVERY rule in this file MUST be scoped under `html.dd-desktop`
   (or a descendant thereof). Mobile is the default — this file
   only adds / overrides for wide-viewport + fine-pointer users.

   The `dd-desktop` class is set by a pre-paint script in base.html
   based on a media query (min-width: 900px) and (pointer: fine),
   so there is no flash of the mobile layout before desktop rules
   apply, and no flash of desktop before mobile on narrow windows.

   Layout philosophy on desktop:
     - Wider container (max-width 1280px, bumped from 1100 after
       the app felt cramped on wide monitors).
     - Top-of-page tab strip replaces the fixed bottom nav.
     - Hover states activate (ignored on touch).
     - Slightly larger base type scale so reading across a wider
       viewport feels correct instead of cramped.

   Anything genuinely responsive that belongs in base.css (e.g.
   a reusable component that happens to look fine wide) stays in
   base.css. Only put rules here that change the SHAPE of the page
   on desktop. See CLAUDE.md for the authoritative rule.
   ============================================================ */

/* ── Container + page chrome ─────────────────────────────────
   Wider reading width on desktop. Kills the mobile padding
   reserved for the bottom nav since desktop promotes nav to the
   top; no more dead space under content. 1280px is the default
   shared by header/nav/tab-strip — wide enough to feel like a
   real desktop app but still capped so prose stays readable on
   ultrawide monitors. Data-dense tabs (inventory) can override. */
html.dd-desktop .page-wrap {
  max-width: 1280px;
  padding-bottom: 40px;
}

/* Top chrome grows a little to breathe on desktop. */
html.dd-desktop .sticky-chrome {
  padding-left: 0;
  padding-right: 0;
}
html.dd-desktop .app-header {
  max-width: 1280px;
  margin: 0 auto;
  padding: 14px 28px;
}
html.dd-desktop .app-logo { font-size: 22px; }
html.dd-desktop .app-logo-dragon { height: 32px; }

/* ── Bottom nav → top nav ────────────────────────────────────
   Three separate nav surfaces live in this codebase:
     .bottom-nav → mobile-only (both sheet tabs + home app nav)
     .top-nav    → desktop sheet-level tab strip (Overview / Combat / …)
     .app-nav    → desktop global nav (Characters / Campaigns / Friends /
                   More) always visible in the sticky chrome.
   Toggle visibility per device class so each renders exactly once. */
html.dd-desktop .bottom-nav { display: none !important; }
html.dd-mobile  .top-nav,
html.dd-mobile  .app-nav    { display: none !important; }

/* ── App nav (desktop, global) ────────────────────────────────
   Renders below the header, above the sheet tab strip (if any).
   Uses the same visual vocabulary as .top-nav so a sheet page
   shows a consistent two-tier nav hierarchy. */
html.dd-desktop .app-nav {
  display: flex;
  max-width: 1280px;
  margin: 0 auto;
  padding: 0 16px;
  gap: 2px;
  background: var(--black-1);
  border-bottom: 1px solid var(--grey-dark);
}
/* Nav-item dimensions match .top-nav exactly (padding/font/icon)
   so the .app-nav row on the home page and the .top-nav row on
   sheet pages render at identical heights. Diverging values were
   producing a visible 6px height difference between surfaces. */
html.dd-desktop .app-nav .nav-item {
  position: relative;
  flex: 0 0 auto;
  flex-direction: row;
  gap: 8px;
  padding: 12px 16px;
  min-height: 0;
  border-bottom: 2px solid transparent;
  color: var(--grey-mid);
  font-size: 13px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  font-family: var(--font-display);
  font-weight: 700;
  transition: color var(--transition), border-color var(--transition),
              background var(--transition);
}
html.dd-desktop .app-nav .nav-item:hover {
  color: var(--white);
  background: var(--black-3);
}
html.dd-desktop .app-nav .nav-item.active {
  color: var(--red-bright);
  border-bottom-color: var(--red);
}
html.dd-desktop .app-nav .nav-item svg { width: 18px; height: 18px; }
html.dd-desktop .app-nav .nav-lbl {
  font-size: 12px;
  letter-spacing: 0.09em;
}
html.dd-desktop .app-nav .nav-badge {
  position: absolute;
  top: 4px;
  right: auto;
  left: 26px;
  min-width: 16px;
  height: 16px;
  padding: 0 4px;
  font-size: 10px;
  line-height: 16px;
  border-radius: 8px;
  background: var(--red);
  color: var(--white);
  text-align: center;
}

html.dd-desktop .top-nav {
  display: flex;
  max-width: 1280px;
  margin: 0 auto;
  padding: 0 16px;
  background: var(--black-2);
  border-bottom: 1px solid var(--grey-dark);
  gap: 2px;
}
html.dd-desktop .top-nav .nav-item {
  flex: 0 0 auto;
  flex-direction: row;
  gap: 8px;
  padding: 12px 16px;
  min-height: 0;
  border-bottom: 2px solid transparent;
  font-size: 13px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  font-family: var(--font-display);
  font-weight: 700;
  transition: color var(--transition), border-color var(--transition),
              background var(--transition);
}
html.dd-desktop .top-nav .nav-item:hover {
  color: var(--white);
  background: var(--black-3);
}
html.dd-desktop .top-nav .nav-item.active {
  color: var(--red-bright);
  border-bottom-color: var(--red);
  background: transparent;
}
html.dd-desktop .top-nav .nav-item svg { width: 18px; height: 18px; }
html.dd-desktop .top-nav .nav-lbl {
  font-size: 12px;
  letter-spacing: 0.09em;
}
/* Badge repositioning for horizontal layout — float it over the
   icon instead of the original top-of-column offset. */
html.dd-desktop .top-nav .nav-badge {
  position: absolute;
  top: 6px;
  right: auto;
  left: 24px;
}

/* ── Hover states (mobile never gets these — touch doesn't have
   a meaningful hover, and stale hover-on-tap states feel broken
   on iOS). Only apply where the element doesn't already define
   its own :hover in base.css. */
html.dd-desktop .btn-ghost:not(:disabled):hover {
  background: var(--black-3);
  border-color: var(--grey-mid);
}
/* Hover + open-disclosure: theme accent on every header icon button.
   Was --white; that diverged from sibling <a class="header-icon-btn">
   elements which the broader a:not(.btn):not(.nav-item):hover rule
   below tints theme-red, leaving <button class="header-icon-btn"> the
   only outlier. Unified to --red-bright. See base.css for the canonical
   rule + the aria-expanded pinning that mirrors `.nav-item.active`. */
html.dd-desktop .header-icon-btn:hover,
html.dd-desktop .header-icon-btn[aria-expanded="true"] {
  color: var(--red-bright);
}
html.dd-desktop a:not(.btn):not(.nav-item):hover {
  color: var(--red-bright);
}

/* ── My-turn FAB + dice FAB on desktop ───────────────────────
   Both are 54×54 circles anchored to the lower-right of the
   content column (not the viewport edge — otherwise they float
   300+ px past the content on a 1440px monitor).

   Higher specificity (html.dd-desktop body .xxx) because
   base.html has trailing <style> blocks with
   body:has(.bottom-nav) .dd-dice-fab rules. The :has() matches on
   desktop too since .bottom-nav is still in the DOM (display:none).
   Beating those rules keeps the FABs planted at bottom:28px on
   desktop instead of floating 82px up for a nav that isn't there. */
html.dd-desktop body .dd-dice-fab {
  position: fixed;
  left: auto;
  right: calc(max(24px, (100vw - 1280px) / 2) + 20px);
  bottom: 28px;
}
html.dd-desktop body .my-turn-fab {
  position: fixed;
  left: auto;
  /* 54px dice width + 10px gap + 20px content inset = 84px clear */
  right: calc(max(24px, (100vw - 1280px) / 2) + 84px);
  bottom: 28px;
}
/* B4 desktop reflow: with Virtual Dice off the dice FAB is hidden, so
   My Turn slides into the dice's corner slot (+20px) instead of floating
   84px in with an empty gap to its right. Mirrors the mobile reflow in
   base.css (html.dd-virtual-dice-off .my-turn-fab { right: 18px }).
   3-class specificity beats the html.dd-desktop body rule above. */
html.dd-desktop.dd-virtual-dice-off body .my-turn-fab {
  right: calc(max(24px, (100vw - 1280px) / 2) + 20px);
}

/* ── My Turn modal — desktop card override ──────────────────
   The base .my-turn-modal is position:fixed; inset:0; flex-column —
   designed for mobile where edge-to-edge full-screen IS the right
   shape. On desktop, edge-to-edge stretches the chrome past the
   readable column and reads as a top-of-page banner, not a modal.

   Fix: keep the fixed inset:0 (so the dark scrim still fills the
   viewport) but center the header + body as a capped-width card
   stack inside it. Header gets rounded top corners + border; body
   gets rounded bottom + border; together they read as one card on
   the scrim. The base mobile rules stay intact — this only fires
   under html.dd-desktop. */
html.dd-desktop .my-turn-modal {
  align-items: center;
  padding: 32px 24px;
}
html.dd-desktop .my-turn-modal .modal-header,
html.dd-desktop .my-turn-modal .modal-body {
  width: min(720px, 100%);
  /* Override the mobile.css @media (min-width:600px) cap that pinned
     .modal-body to max-width:600px — that rule is shared with the
     legacy mobile-modal pattern and predates the dd-desktop scope.
     We need the body to match the 720px header width on desktop so
     the card reads as a single column, not a wide banner over a
     narrow body. */
  max-width: 720px;
  margin: 0 auto;
}
html.dd-desktop .my-turn-modal .modal-header {
  border-radius: var(--radius) var(--radius) 0 0;
  border: 1px solid var(--grey-dark);
  border-bottom: 2px solid var(--red);
  /* Override the safe-area top inset — desktop browsers have no
     home-indicator chin. */
  padding-top: 14px;
}
html.dd-desktop .my-turn-modal .modal-body {
  background: var(--black-3);
  border: 1px solid var(--grey-dark);
  border-top: none;
  border-radius: 0 0 var(--radius) var(--radius);
  /* The flex:1 1 auto from base.css makes the body grow to fill the
     remaining column. With our 32px + 32px viewport padding the body
     gets ~85vh; its overflow-y:auto handles content beyond that. */
  flex: 0 1 auto;
  /* Same safe-area override — no home-indicator. */
  padding-bottom: 16px;
}

/* Body scroll lock while the modal is open. Without this, the page
   scrollbar stays active behind the modal scrim, producing the
   "double scrollbar" the user flagged (modal-body scrolls + page
   body scrolls). :has() is modern-browsers-only; gracefully no-ops
   on older browsers — they'd see the old double-scroll but the rest
   of the chrome is fine. Scoped to desktop because mobile uses the
   edge-to-edge full-screen modal which already covers the page; the
   double-scroll regression was desktop-specific. */
html.dd-desktop:has(.my-turn-modal.open) body {
  overflow: hidden;
}

/* ── Section + card spacing — a little more air on desktop. */
html.dd-desktop .section { padding: 22px 28px 0; }

/* ── Tab-content multi-column layout ─────────────────────────
   The tab-content wrapper (see _sheet_base.html) becomes a
   CSS-columns container on desktop so the stack of sections a
   mobile user scrolls through gets redistributed across two
   columns. CSS columns (rather than grid) because: sections have
   wildly different heights, columns auto-balance, and content
   order is preserved (first in source = top of col 1).

   The first section (or anything flagged .tab-hero) spans all
   columns so the character header / full-width primary block
   stays edge-to-edge.

   break-inside: avoid stops a long section (Skills, say) from
   splitting across the column boundary mid-card. */
html.dd-desktop .tab-content {
  column-count: 2;
  column-gap: 28px;
  padding: 0 28px;
}
html.dd-desktop .tab-content > .section {
  break-inside: avoid;
  padding: 22px 0 0;
  margin-bottom: 4px;
}
html.dd-desktop .tab-content > .section:first-child,
html.dd-desktop .tab-content > .section.tab-hero,
html.dd-desktop .tab-content > .tab-hero {
  column-span: all;
  padding: 22px 0 0;
}

/* Some tab content isn't in <section> wrappers (inventory list,
   campaign cards, etc.). Children at the top level that aren't a
   .section still need break-inside protection so a card doesn't
   split across the column boundary. */
html.dd-desktop .tab-content > * {
  break-inside: avoid-column;
}

/* Per-tab refinements. Most tabs are fine with the default 2-col
   flow; spot-tweaks go here so each gets exactly the shape it
   needs on desktop without polluting the shared rule. */

/* Inventory: reference cards (Encumbrance + Currency) pair
   horizontally in a top strip; the main Items list uses the
   full desktop width because each row is dense (name + damage +
   weight + qty stepper + equip + attune + edit), and cutting
   the width back wastes the horizontal room this tab benefits
   from most. Mobile: .inv-grid-top is a plain block and
   sections stack. */
html.dd-desktop .tab-content-inventory {
  column-count: 1;
}
html.dd-desktop .tab-content-inventory .inv-grid-top {
  display: grid;
  grid-template-columns: 1fr 1fr;
  column-gap: 24px;
  align-items: start;
}
html.dd-desktop .tab-content-inventory .inv-grid-top > .section {
  padding: 22px 0 0;
}

/* Bio: single-column flow so Characteristics and Backstory don't
   split across the 2-col tab-content rule. The two compact top
   cards (Background display + Appearance) pair horizontally via
   .bio-grid-top below. Bio uses the same outer width as every
   other character-sheet tab on desktop — no centered max-width
   cap (an earlier 820px cap made Bio read as "shrunk" next to
   Features / Combat / Spells / RP, which all span the full sheet
   column). Mobile: the wrapper is a plain block and all four
   sections stack. */
html.dd-desktop .tab-content-bio {
  column-count: 1;
}
html.dd-desktop .tab-content-bio .bio-grid-top {
  display: grid;
  grid-template-columns: 1fr 1fr;
  column-gap: 24px;
  align-items: start;
}
html.dd-desktop .tab-content-bio .bio-grid-top > .section {
  padding: 22px 0 0;
}

/* Features: each category (Class Features, Racial Traits, Feats …)
   gets its OWN 2-col card flow on desktop so cards stay grouped
   under their category label.

   Uses CSS multi-column (not grid) because feature cards have
   wildly different heights — a 2-line trait sits next to an 80-line
   Spellcasting card. CSS Grid with `align-items: start` leaves dead
   vertical space inside each row cell when one side is much taller
   than the other; multi-column packs each column independently so
   a short card is immediately followed by the next card underneath
   it, with no row-height ghost padding.

   break-inside: avoid-column keeps each card from splitting across
   the column boundary. Mobile: .feat-group is a plain block so
   cards stack 1-wide. */
html.dd-desktop .tab-content-features {
  column-count: 1;
  padding: 0 28px;
}
html.dd-desktop .tab-content-features > .section {
  padding: 22px 0 0;
  break-inside: auto;
}
html.dd-desktop .tab-content-features .feat-group {
  column-count: 2;
  column-gap: 20px;
}
html.dd-desktop .tab-content-features .feat-group > .card {
  break-inside: avoid-column;
  /* Keep the mobile `margin-bottom: 8px` from features.html inline
     so cards have vertical breathing room within a column. */
}
/* .feat-group-label styling lives in base.css (font size, color,
   underline, margins) so it's consistent across mobile + desktop. */

/* ── Campaign: full-width header/chat/notes + 2-col records ─
   The campaign header, chat panel, and Running Notes stay full
   width on desktop — they're either context, an interactive
   component with its own layout, or a prose-input card. The five
   narrative record sections (Relationships, NPCs, Quests, Session
   Log, Locations) pair into two columns below:

     Left  (camp-col-main): Relationships, NPCs
     Right (camp-col-side): Quests, Session Log, Locations

   Mobile: .camp-grid / .camp-col are plain blocks and sections
   flow in source order (unchanged from before). */
html.dd-desktop .tab-content-campaign {
  column-count: 1;
  padding: 0 28px;
}
html.dd-desktop .tab-content-campaign > .section {
  padding: 22px 0 0;
  break-inside: auto;
}
html.dd-desktop .tab-content-campaign .camp-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  column-gap: 28px;
  align-items: start;
}
html.dd-desktop .tab-content-campaign .camp-col {
  display: flex;
  flex-direction: column;
  min-width: 0;
}
html.dd-desktop .tab-content-campaign .camp-col > .section {
  padding: 22px 0 0;
}

/* Campaign empty state (unjoined character) — cap the two action
   buttons so they don't stretch the full card width on desktop.
   Card body (title + paragraph) still fills the row for readable
   line-length; only the buttons shrink to natural pill size and
   left-align on the card edge. */
html.dd-desktop .tab-content-campaign .camp-empty .camp-create-details,
html.dd-desktop .tab-content-campaign .camp-empty .camp-empty-link {
  align-self: flex-start;
  width: auto;
  min-width: 220px;
  max-width: 260px;
}
html.dd-desktop .tab-content-campaign .camp-empty .camp-create-summary {
  width: 100%;
}

/* ── Spells: reference-card top strip + full-width list ────
   The Spellcasting summary (Save DC / Atk / ability) and the Spell
   Slots tracker are reference/state cards — on mobile they stack
   above the filters + list; on desktop they pair horizontally into
   a top strip, freeing vertical room before the actual spell list.

   The spell list itself stays full-width: it's the main tool on
   this page and benefits from the whole column for scanning spell
   names + favourite toggles. */
html.dd-desktop .tab-content-spells {
  column-count: 1;
  padding: 0 28px;
}
html.dd-desktop .tab-content-spells > .section {
  padding: 22px 0 0;
  break-inside: auto;
}
html.dd-desktop .tab-content-spells .sp-grid-top {
  display: grid;
  grid-template-columns: 1fr 1fr;
  column-gap: 28px;
  align-items: start;
}
html.dd-desktop .tab-content-spells .sp-grid-top > .section {
  padding: 22px 0 0;
}

/* ── Hide the global app-nav on sheet pages ─────────────────
   Desktop renders both the app-level nav (Characters / Campaigns
   / Friends / More) and the sheet-level tab strip (Overview /
   Combat / Spells / …) in sticky chrome. On a sheet page the
   user is already inside Characters — the home nav reading
   "CHARACTERS" as a tab below the logo adds visual noise without
   giving them a place to go they couldn't already reach.

   The sticky chrome only contains a .top-nav when _sheet_base.html
   renders its sticky_extra block, so :has(.top-nav) is a precise
   signal for "we're on a sheet page." Non-sheet pages keep the
   app-nav. Mobile is unaffected — .app-nav is display:none there
   regardless of what else is rendered. */
html.dd-desktop .sticky-chrome:has(.top-nav) .app-nav {
  display: none !important;
}

/* ── Universal search → merged into chip strip on desktop ────
   _chip_strip.html runs a small script on desktop that MOVES the
   .search-wrap out of its standalone section at the top of the
   tab content and INTO the chip strip. The standalone section
   read as an orphaned 560px bar with empty space to its right;
   folding it into the chip strip gives the whole row a proper
   dashboard-header feel — at-a-glance stats on the left, search
   on the far right, single compact band above the tab content.

   Chip strip itself switches from overflow-scroll to flex-wrap
   on desktop so both the chips and the search stay visible;
   margin-left:auto on the search pushes it to the right edge of
   whichever row it lands on.

   The .dd-search-section wrapper that holds the search at parse
   time is hidden pre-paint on desktop — html.dd-desktop is set by
   base.html's pre-paint script BEFORE first paint, so the source
   section never flashes between "in tab content" and "in chip
   strip" on cross-tab nav. The relocator IIFE still runs and
   reparents the .search-wrap into #dd_chip_strip; once moved, the
   wrap inherits chip-strip layout and is visible there. */
html.dd-desktop .dd-search-section { display: none; }
html.dd-desktop .chip-strip {
  flex-wrap: wrap;
  overflow-x: visible;
  row-gap: 6px;
  align-items: center;
}
html.dd-desktop .chip-strip .search-wrap {
  margin: 0 0 0 auto;
  width: 280px;
  max-width: 280px;
  flex-shrink: 0;
}
html.dd-desktop .chip-strip .search-input {
  padding: 6px 12px 6px 32px;
  font-size: 12px;
  min-height: 32px;
}
html.dd-desktop .chip-strip .search-icon {
  font-size: 12px;
  left: 10px;
}
/* X-clear button — base.css sets 32×32, but mobile.css's universal
   `button { min-height: 36px }` floor stretches it back to 36px tall
   on every viewport (mobile.css is always-on, not mobile-scoped).
   On desktop the search-input is only 32px tall, so a 36px clear
   button bulges 2px above + below the input frame — visually reads
   as "X bleeding out of the search bar." Pin the desktop floor +
   shape to a tight 28×28 square so it sits comfortably inside the
   32px input with 2px breathing room. */
html.dd-desktop .chip-strip .search-clear {
  width: 28px;
  height: 28px;
  min-height: 28px;
  right: 4px;
}
html.dd-desktop .chip-strip .search-clear svg {
  width: 14px;
  height: 14px;
}
/* Dropdown of search results should still align to the input's
   left edge and be full-width; the base `left:0; right:0` rule
   already does this since search-results is absolutely positioned
   inside search-wrap. Explicit min-width for wider hit menus. */
html.dd-desktop .chip-strip .search-results {
  min-width: 360px;
  right: 0;
  left: auto;
}

/* ── Home-page list → card grid on desktop ───────────────────
   Mobile: a single column of full-width rows works fine. Desktop:
   each row stretches 1000px+ with a two-line payload, leaving
   dead space in the middle — "mobile but wider" again.

   Scoped to `.page-wrap > .section > .rows-list` so it ONLY hits
   home pages (Characters, Campaigns, Friends, More, Invitations).
   Sheet tabs nest their rows-lists inside `main.tab-content` so
   `.page-wrap > .section` doesn't match — inventory rows, NPCs,
   and other detail-heavy lists stay as full-width rows because
   they carry inline controls (qty stepper, equip, attune, edit)
   that a grid layout would crowd. */
html.dd-desktop .page-wrap > .section > .rows-list {
  background: transparent;
  border: none;
  border-radius: 0;
  overflow: visible;
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 10px;
}
html.dd-desktop .page-wrap > .section > .rows-list > .data-row,
html.dd-desktop .page-wrap > .section > .rows-list > a.data-row {
  background: var(--black-2);
  border: 1px solid var(--grey-dark);
  border-radius: var(--radius);
  padding: 14px 16px;
  min-height: 60px;
}
html.dd-desktop .page-wrap > .section > .rows-list > .data-row:last-child {
  /* Kill the base.css "last-child no border" rule — every card in
     the grid needs its own border. */
  border-bottom: 1px solid var(--grey-dark);
}
html.dd-desktop .page-wrap > .section > .rows-list > .data-row:hover {
  border-color: var(--red);
  background: var(--black-3);
}

/* ── Kill "stretched mobile" button groups ────────────────────
   On mobile, a lot of action rows use flex:1 on children or
   .btn-block width:100% so every button fills the column — that's
   right for narrow viewports. On desktop the same rules let a
   "Prev Turn" button be 257px wide and an "Encounter Reset"
   button span 1044px, which reads like a banner. Cap each group
   to natural width and let empty space sit to the right.

   Mobile is unaffected — these rules are all inside html.dd-desktop. */

/* Initiative flow: Prev / End Turn / Next Round / Clear All. On
   mobile .init-flow .btn has flex:1. Drop it on desktop so each
   button is its natural size + a small min-width for readability. */
html.dd-desktop .init-flow .btn {
  flex: 0 0 auto;
  min-width: 110px;
}

/* Action Economy toggles (Bonus Action / Reaction / Sneak Attack).
   The .ae-grid auto-fits tiles; on desktop cap the column width so 3-4 cards
   don't stretch across the full band, and left-align them. */
html.dd-desktop #dd-action-economy .ae-grid {
  grid-template-columns: repeat(auto-fit, minmax(140px, 180px));
  justify-content: start;
}

/* Encounter reset — a destructive action that should NOT read
   as the primary CTA on the page. Compact pill, not a banner. */
html.dd-desktop #encounter_reset.btn-block {
  width: auto;
  min-width: 180px;
  max-width: 240px;
}

/* Global: any .btn-block left in combat/spells/campaign/bio tab
   content should stop full-widthing on desktop. Desktop has the
   horizontal room to show the button at its content width; the
   surrounding row still keeps it prominent via its red/ghost
   styling. Overview's HP damage/heal buttons have their own
   .hp-btn rules and aren't .btn-block, so they're untouched. */
html.dd-desktop .tab-content .btn-block:not(.hp-btn):not(.rest-foot .btn-block) {
  width: auto;
  align-self: flex-start;
  min-width: 180px;
}

/* Rest row on Overview (Short Rest / Long Rest) still needs the
   two buttons paired 50/50 as a single decision row, so un-cap
   them back to their shared flex:1 layout. */
html.dd-desktop .tab-content-overview .rest-row .btn-block {
  width: 100%;
  flex: 1 1 0;
  min-width: 0;
  max-width: none;
}

/* Resource bar: on mobile chips scroll horizontally; on desktop
   there's room to wrap them into a flex-wrap grid so the user
   sees every slot level at a glance without scrubbing sideways. */
html.dd-desktop .resource-bar {
  flex-wrap: wrap;
  overflow-x: visible;
}

/* Condition badge list: same treatment — let the pills wrap into
   multiple rows rather than clipping or scrolling. */
html.dd-desktop .condition-list {
  gap: 8px;
}

/* ── HP block compact layout on desktop ──────────────────────
   Mobile stacks the HP bar row (label + bar + numbers) above the
   damage / heal buttons — right call when vertical is cheap and
   horizontal is tight. On desktop the same column stack reads as
   "mobile but wider": a skinny bar dragged out to 1000px with the
   four little buttons crowded into one corner below.

   Flatten the whole block to a single row: bar in the middle
   (capped so it doesn't sprawl), buttons on the right. Compact,
   dashboard-y, uses the width without stretching the bar. */
html.dd-desktop .hp-block {
  flex-direction: row;
  align-items: center;
  gap: 20px;
  padding: 10px 16px;
}
html.dd-desktop .hp-block .hp-main {
  /* HP bar takes ~60% of the row on desktop; the 4 delta buttons
     get the remaining ~40%. Both can shrink if the parent is
     narrower (half-column grids), so the same rule works in the
     full-width Combat HP section and inside the Overview char-
     header. min-width: 0 lets the inner bar-wrap collapse only as
     a last resort, not as a default. */
  flex: 1 1 60%;
  min-width: 0;
}
html.dd-desktop .hp-block .hp-controls {
  flex: 0 0 auto;
  justify-content: flex-end;
}
html.dd-desktop .hp-block .hp-btn {
  flex: 0 0 auto;
  min-width: 56px;
  max-width: 72px;
  height: 36px;
}

/* ── Combat: full-width top band + two intentional columns ─
   Top strip stays full width so every at-a-glance combat read
   (Initiative order, Action Economy chips, HP bar) spans the
   page. Below that, two columns:

     Left  (cb-col-main) — what you SPEND on your turn:
                           Class Features modules + Equipped Weapons
     Right (cb-col-side) — what you TRACK across the fight:
                           Resources, Survival, Conditions

   Encounter reset sits full-width at the bottom as an endcap.
   Mobile layout is unaffected — .cb-grid / .cb-col are plain
   block wrappers there, and sections flow in source order. */
html.dd-desktop .tab-content-combat {
  column-count: 1;
  padding: 0 28px;
}
html.dd-desktop .tab-content-combat > .section {
  padding: 22px 0 0;
  break-inside: auto;
}
html.dd-desktop .tab-content-combat .cb-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  column-gap: 28px;
  align-items: start;
}
html.dd-desktop .tab-content-combat .cb-col {
  display: flex;
  flex-direction: column;
  min-width: 0;
}
html.dd-desktop .tab-content-combat .cb-col > .section {
  padding: 22px 0 0;
}

/* ── Overview: intentional desktop layout ────────────────────
   Mobile layout stacks the char-header, then ability scores,
   then the four secondary sections (Saves, Skills, Passive,
   Profs). On desktop the column-count:2 default splits those
   randomly and reads as "mobile but wider." Replace with an
   explicit layout:

     Row 1 — char-header (full width)
     Row 2 — Ability Scores (full width, 6 cards across)
     Row 3 — two real columns:
               • left  (ov-col-rolls)  — Saves, Skills
               • right (ov-col-ref)    — Passive, Proficiencies

   This is layout-as-information-architecture: "things you roll"
   live beside each other, "reference info" lives beside itself.
   Kills the flipped-a-coin feel of column-count shuffling. */
html.dd-desktop .tab-content-overview {
  column-count: 1;
  padding: 0 28px;
}
html.dd-desktop .tab-content-overview > .section {
  padding: 22px 0 0;
  break-inside: auto;
}

/* Ability Scores: spread all 6 cards in a single horizontal row
   at full width. Mobile keeps its default 3-column grid via
   base.css; the desktop override only applies inside overview. */
html.dd-desktop .tab-content-overview .ov-abilities .stats-grid {
  grid-template-columns: repeat(6, 1fr);
}

/* .ov-grid on mobile = invisible block wrapper (no style needed).
   On desktop it becomes the 2-col layout. align-items:start stops
   the columns from stretching to match each other's height. */
html.dd-desktop .tab-content-overview .ov-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  column-gap: 28px;
  align-items: start;
}
html.dd-desktop .tab-content-overview .ov-col {
  display: flex;
  flex-direction: column;
  min-width: 0;       /* let flex children shrink past content min */
}
html.dd-desktop .tab-content-overview .ov-col > .section {
  padding: 22px 0 0;
}

/* ── Overview char-header polish on desktop ──────────────────
   Give the vitals and HP block more horizontal breathing room.
   The vitals grid already lays out as 4 columns via .char-vitals
   in base.css; ensure it keeps that on desktop even inside the
   wider column. Bumping HP-bar min-height a touch so the empty
   red outline reads properly at this width. */
html.dd-desktop .tab-content-overview .char-header {
  max-width: 100%;
}
html.dd-desktop .tab-content-overview .char-header .hp-bar-wrap {
  min-height: 20px;
}

/* ── UI-mode override toggle helper.
   Users who WANT the mobile layout on their desktop (or vice
   versa) can set `localStorage.dd_ui_mode`. Settings page should
   eventually expose a switch for this; for now it's a power-user
   escape hatch. */
