/* =============================================================================
   Studio Royal Art — Design system
   =============================================================================
   Stage 1 of docs/UI_UX_AUDIT.md's redesign plan: real design tokens instead
   of three brand-color variables sitting on unmodified Bootstrap defaults.

   Deliberately CSS-only. Bootstrap 5.3 (vendored below in base.html, not a
   CDN — the app has to work on a restricted network) exposes almost every
   component's colours, radius and spacing as CSS custom properties, which is
   its own official theming mechanism: this file overrides those variables at
   :root and per-component rather than duplicating Bootstrap's rules or
   touching template markup. That means every existing template — every
   .btn-studio, every plain .btn-primary, every .card, every .form-control —
   re-themes automatically, with zero HTML changes and zero risk to the
   Python-side tests, which only ever inspect rendered text/structure, never
   CSS.

   The PDF itself never loads this file — its styling is fixed and separate,
   in app/templates/pdf/ — by design, so a screen redesign can never drift the
   generated document's own fidelity to the archive.
   ========================================================================= */

:root {
  /* ---- brand ---------------------------------------------------------- */
  --studio-cream: #fff2cc;
  --studio-gold: #806000;
  --studio-gold-dark: #5c4600;   /* hover/active state for gold buttons */
  --studio-gold-soft: rgba(128, 96, 0, 0.08);
  --studio-gold-border: rgba(128, 96, 0, 0.25);

  /* ---- shell: dark bronze from the letterhead gold ---------------------- */
  --studio-shell: #2b220c;
  --studio-shell-hover: #3d3113;
  --studio-shell-active: #4a3b14;
  --studio-shell-line: #44381b;
  --studio-shell-text: #ece3cc;
  --studio-shell-muted: #b5a682;
  --studio-shell-gold: #e0b84a;

  /* ---- money states (bills): paid / part paid / owed ------------------- */
  --studio-paid: #2f7a3e;
  --studio-owed: #b4531f;
  --studio-track: #ebe4d4;

  /* ---- neutrals ---------------------------------------------------------
     A warm-biased grey scale (a touch of the brand's gold hue mixed in)
     rather than Bootstrap's cool default greys, so borders/muted text read
     as chosen, not inherited. */
  --studio-ink: #2a2620;
  --studio-ink-muted: #6b6154;
  --studio-border: #e4ddd0;
  --studio-surface: #ffffff;
  --studio-bg: #faf7f0;

  /* ---- type scale --------------------------------------------------------
     One scale, used consistently: page title / section title / body /
     label / helper text / table text / numbers / metadata. */
  --studio-font-sans: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
    "Helvetica Neue", Arial, sans-serif;
  --studio-text-page-title: 1.5rem;     /* h1 — "Quotations", "QT-2026-001" */
  --studio-text-section-title: 1.0625rem; /* card headers, h2 */
  --studio-text-body: 0.9375rem;
  --studio-text-label: 0.8125rem;
  --studio-text-helper: 0.8125rem;
  --studio-text-table: 0.875rem;
  --studio-text-meta: 0.8125rem;

  /* ---- spacing -------------------------------------------------------
     A single reference scale so components stop picking arbitrary
     rem values. Matches Bootstrap's own spacer scale (already used via
     .mb-3/.g-3/etc. throughout the templates) so nothing has to change
     there — this just names it for anything new. */
  --studio-space-xs: 0.25rem;
  --studio-space-sm: 0.5rem;
  --studio-space-md: 1rem;
  --studio-space-lg: 1.5rem;
  --studio-space-xl: 2.5rem;

  /* ---- elevation -------------------------------------------------------
     Restrained: one soft shadow, used for hover/lift only, not stamped on
     every card by default (a bordered flat card is the resting state). */
  --studio-shadow-sm: 0 1px 2px rgba(42, 38, 32, 0.06);
  --studio-shadow-md: 0 4px 12px rgba(42, 38, 32, 0.10);

  /* ---- Bootstrap root tokens --------------------------------------------
     These cascade into every component that references var(--bs-*) at
     the root (cards, tables, alerts, body text) without a per-class
     override. Buttons/badges/inputs bake their own colours per-class at
     build time, so they're re-themed individually further down. */
  --bs-body-font-family: var(--studio-font-sans);
  --bs-body-font-size: var(--studio-text-body);
  --bs-body-color: var(--studio-ink);
  --bs-body-bg: var(--studio-bg);
  --bs-border-color: var(--studio-border);
  --bs-border-color-translucent: var(--studio-border);
  --bs-border-radius: 0.5rem;
  --bs-border-radius-sm: 0.375rem;
  --bs-border-radius-lg: 0.625rem;
  --bs-secondary-color: var(--studio-ink-muted);
  --bs-link-color: var(--studio-gold);
  --bs-link-hover-color: var(--studio-gold-dark);
  --bs-link-color-rgb: 128, 96, 0;
  --bs-link-hover-color-rgb: 92, 70, 0;
  --bs-emphasis-color: var(--studio-ink);
}

body {
  color: var(--studio-ink);
  background: var(--studio-bg);
  -webkit-font-smoothing: antialiased;
}

/* -------------------------------------------------------------- headings */

h1, .h1 { font-size: var(--studio-text-page-title); font-weight: 600; letter-spacing: -0.01em; }
h2, .h2 { font-size: 1.25rem; font-weight: 600; }
h3, .h3 { font-size: var(--studio-text-page-title); font-weight: 600; letter-spacing: -0.01em; }
h4, .h4 { font-size: var(--studio-text-section-title); font-weight: 600; }
h5, .h5, h6, .h6 { font-weight: 600; }

/* Card headers double as section titles throughout the app (card-header is
   used far more than a bare h2) — give it the same weight/size the type
   scale defines for a section title, once, instead of each card guessing. */
.card-header {
  font-size: var(--studio-text-section-title);
  font-weight: 600;
}

.form-label {
  font-size: var(--studio-text-label);
  font-weight: 600;
  color: var(--studio-ink);
}

.form-text, small, .small {
  font-size: var(--studio-text-helper);
}

table, .table {
  font-size: var(--studio-text-table);
}

/* Document metadata lines ("28 Apr 2025 · Miss Ayesha · Sent") — the
   .text-muted small pattern already used across every detail page header. */
.text-muted {
  color: var(--studio-ink-muted) !important;
}

/* ------------------------------------------------------------- app shell
   A dark bronze rail taken from the letterhead's gold, so the working area
   stays a calm light page for daylight in the shop and on a phone outdoors.
   Phones get a bottom bar in thumb reach instead of a hidden menu. */

.studio-app-shell {
  display: flex;
  min-height: 100vh;
  align-items: stretch;
}

.ico {
  width: 1.25rem;
  height: 1.25rem;
  flex: 0 0 auto;
  vertical-align: -0.25em;
}

.studio-sidebar {
  flex: 0 0 240px;
  width: 240px;
  flex-direction: column;
  background: var(--studio-shell);
  color: var(--studio-shell-text);
  position: sticky;
  top: 0;
  height: 100vh;
  overflow-y: auto;
  scrollbar-color: var(--studio-shell-line) transparent;
}

.studio-wordmark {
  display: block;
  font-family: Georgia, "Times New Roman", serif;
  font-size: 1.2rem;
  font-weight: 700;
  color: var(--studio-shell-gold);
  text-decoration: none;
  letter-spacing: 0.005em;
}
.studio-wordmark:hover { color: #fff; }
.studio-sidebar > .studio-wordmark { padding: 1.35rem 1.25rem 1rem; }

.studio-new-menu { padding: 0 1rem 0.75rem; }
.studio-new-btn {
  --bs-btn-color: var(--studio-shell);
  --bs-btn-bg: var(--studio-shell-gold);
  --bs-btn-border-color: var(--studio-shell-gold);
  --bs-btn-hover-color: var(--studio-shell);
  --bs-btn-hover-bg: #fff;
  --bs-btn-hover-border-color: #fff;
  --bs-btn-active-bg: #fff;
  --bs-btn-active-color: var(--studio-shell);
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.4rem;
  font-weight: 600;
}
.studio-new-btn::after { margin-left: auto; }

.studio-sidebar-nav {
  padding: 0.25rem 0.75rem 1rem;
  flex: 1 1 auto;
}

.studio-nav-group-label {
  font-size: 0.75rem;
  font-weight: 600;
  color: var(--studio-shell-muted);
  padding: 1.1rem 0.65rem 0.35rem;
}

.studio-nav-link {
  display: flex;
  align-items: center;
  gap: 0.7rem;
  padding: 0.5rem 0.65rem;
  border-radius: var(--bs-border-radius-sm);
  color: var(--studio-shell-text);
  font-weight: 500;
  font-size: 0.925rem;
  text-decoration: none;
  margin-bottom: 1px;
}
.studio-nav-link .ico { color: var(--studio-shell-muted); }
.studio-nav-link:hover { background: var(--studio-shell-hover); color: #fff; }
.studio-nav-link[aria-current="page"] {
  background: var(--studio-shell-active);
  color: #fff;
  font-weight: 600;
}
.studio-nav-link[aria-current="page"] .ico { color: var(--studio-shell-gold); }

.studio-sidebar-user {
  padding: 0.85rem 1rem;
  border-top: 1px solid var(--studio-shell-line);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem;
  font-size: 0.85rem;
  color: var(--studio-shell-muted);
}
.studio-signout {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  background: none;
  border: 0;
  padding: 0.3rem 0.4rem;
  border-radius: var(--bs-border-radius-sm);
  color: var(--studio-shell-text);
  font-size: 0.85rem;
}
.studio-signout:hover { background: var(--studio-shell-hover); color: #fff; }
.studio-signout .ico { width: 1rem; height: 1rem; }

.studio-mobile-topbar {
  display: flex;
  align-items: center;
  padding: 0.7rem 1rem;
  padding-top: max(0.7rem, env(safe-area-inset-top));
  background: var(--studio-shell);
  position: sticky;
  top: 0;
  z-index: 1020;
}

.studio-main {
  flex: 1 1 auto;
  min-width: 0;
  padding: 1.75rem 2.25rem 3rem;
}
.studio-main-standalone { padding-top: 8vh; }

/* Phone bottom bar. Five equal targets, labels under icons; "New" is the
   one filled button because starting a quote is the job. */
.studio-tabbar {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 1030;
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  background: var(--studio-shell);
  padding: 0.35rem 0.25rem;
  padding-bottom: max(0.35rem, env(safe-area-inset-bottom));
  box-shadow: 0 -4px 16px rgba(43, 34, 12, 0.18);
}
.studio-tabbar > a,
.studio-tabbar > button {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.15rem;
  min-height: 3rem;
  justify-content: center;
  background: none;
  border: 0;
  border-radius: var(--bs-border-radius);
  color: var(--studio-shell-muted);
  font-size: 0.72rem;
  font-weight: 500;
  text-decoration: none;
}
.studio-tabbar > [aria-current="page"] { color: #fff; }
.studio-tabbar > [aria-current="page"] .ico { color: var(--studio-shell-gold); }
.studio-tabbar .ico { width: 1.4rem; height: 1.4rem; }
.studio-tabbar > .studio-tabbar-new { color: var(--studio-shell-gold); font-weight: 600; }
.studio-tabbar-new .ico {
  width: 2.1rem;
  height: 2.1rem;
  padding: 0.35rem;
  border-radius: 50%;
  background: var(--studio-shell-gold);
  color: var(--studio-shell);
}

.studio-sheet { background: var(--studio-shell); color: var(--studio-shell-text); }
.studio-sheet .btn-close { filter: invert(1) grayscale(1) brightness(2); }
.offcanvas-bottom.studio-sheet { height: auto; border-radius: 1rem 1rem 0 0; }
.studio-sheet-actions { display: grid; gap: 0.5rem; padding-bottom: max(1.25rem, env(safe-area-inset-bottom)); }
.studio-sheet-actions a {
  display: flex;
  align-items: center;
  gap: 0.8rem;
  padding: 0.95rem 1rem;
  border-radius: var(--bs-border-radius);
  background: var(--studio-shell-hover);
  color: #fff;
  font-weight: 600;
  text-decoration: none;
}
.studio-sheet-actions a .ico { color: var(--studio-shell-gold); }
#studioMobileNav { width: min(300px, 86vw); }

/* Login wordmark -- Georgia/system serif, not a web font: this app has to
   work on a restricted network, so nothing here can fetch from Google Fonts
   or any other external host. */
.studio-login-mark {
  font-family: Georgia, "Times New Roman", serif;
  font-size: 1.75rem;
  font-weight: 700;
  color: var(--studio-gold);
  letter-spacing: 0.01em;
}

@media (max-width: 991.98px) {
  .studio-app-shell { display: block; min-height: 0; }
  .studio-main { padding: 1.25rem 1rem calc(5.5rem + env(safe-area-inset-bottom)); }
  /* The form's Save bar sits above the bottom bar, not under it. */
  .studio-save-bar { bottom: calc(4rem + env(safe-area-inset-bottom)); }
}

/* ---------------------------------------------------------------- buttons
   Primary = gold (brand), Secondary = neutral outline, Destructive = red
   outline (already Bootstrap's danger, just re-themed to the warm neutral
   family so it doesn't clash), Link = brand-coloured text button. Bootstrap
   bakes each variant's colours into its own --bs-btn-* set rather than
   deriving them from a root theme colour, so each is re-themed explicitly —
   this is Bootstrap 5.3's own documented theming mechanism, not a hack. */

.btn { font-weight: 500; }

.btn-studio,
.btn-primary {
  --bs-btn-color: #fff;
  --bs-btn-bg: var(--studio-gold);
  --bs-btn-border-color: var(--studio-gold);
  --bs-btn-hover-color: #fff;
  --bs-btn-hover-bg: var(--studio-gold-dark);
  --bs-btn-hover-border-color: var(--studio-gold-dark);
  --bs-btn-active-bg: var(--studio-gold-dark);
  --bs-btn-active-border-color: var(--studio-gold-dark);
  --bs-btn-focus-shadow-rgb: 128, 96, 0;
  --bs-btn-disabled-bg: var(--studio-gold);
  --bs-btn-disabled-border-color: var(--studio-gold);
}

.btn-outline-primary {
  --bs-btn-color: var(--studio-gold);
  --bs-btn-border-color: var(--studio-gold);
  --bs-btn-hover-color: #fff;
  --bs-btn-hover-bg: var(--studio-gold);
  --bs-btn-hover-border-color: var(--studio-gold);
  --bs-btn-active-bg: var(--studio-gold-dark);
  --bs-btn-active-border-color: var(--studio-gold-dark);
  --bs-btn-focus-shadow-rgb: 128, 96, 0;
  --bs-btn-disabled-color: var(--studio-gold);
  --bs-btn-disabled-border-color: var(--studio-gold);
}

.btn-secondary,
.btn-outline-secondary {
  --bs-btn-color: var(--studio-ink-muted);
  --bs-btn-border-color: var(--studio-border);
  --bs-btn-hover-color: var(--studio-ink);
  --bs-btn-hover-bg: var(--studio-bg);
  --bs-btn-hover-border-color: var(--studio-ink-muted);
  --bs-btn-active-color: var(--studio-ink);
  --bs-btn-active-bg: var(--studio-bg);
  --bs-btn-active-border-color: var(--studio-ink-muted);
  --bs-btn-focus-shadow-rgb: 107, 97, 84;
}

.btn-link { --bs-btn-color: var(--studio-gold); --bs-btn-hover-color: var(--studio-gold-dark); }

/* .btn-danger / .btn-outline-danger are left on Bootstrap's own red —
   destructive actions keep a universally-understood red rather than the
   brand's warm palette, per "semantic colour is separate from the accent". */

.btn-sm { font-weight: 500; }

/* ----------------------------------------------------------------- forms */

.form-control,
.form-select {
  border-color: var(--studio-border);
}

.form-control:focus,
.form-select:focus {
  border-color: var(--studio-gold);
  box-shadow: 0 0 0 .25rem var(--studio-gold-soft);
}

.form-control:disabled,
.form-select:disabled {
  background-color: var(--studio-bg);
  color: var(--studio-ink-muted);
}

.form-control.is-invalid,
.form-select.is-invalid {
  border-color: #b02a37;
}
.form-control.is-invalid:focus,
.form-select.is-invalid:focus {
  box-shadow: 0 0 0 .25rem rgba(176, 42, 55, 0.15);
}

.form-check-input:checked {
  background-color: var(--studio-gold);
  border-color: var(--studio-gold);
}
.form-check-input:focus {
  border-color: var(--studio-gold);
  box-shadow: 0 0 0 .25rem var(--studio-gold-soft);
}

/* A disabled/loading control gives no feedback today beyond Bootstrap's
   default greyed style -- add a busy cursor so "why isn't this responding"
   at least reads as "working", not "broken", until Stage 2/4 add real
   inline spinners to submit buttons. */
.btn:disabled, .btn.disabled, fieldset:disabled .btn {
  cursor: not-allowed;
}

/* ----------------------------------------------------------------- cards
   Flat + bordered at rest (per "avoid giant rounded cards" / "restrained
   use of colour" — a card is a boundary, not a decoration). Shadow is
   reserved for things that lift on interaction (doc-card below), not
   stamped on every card by default. */

.card {
  border-color: var(--studio-border);
}

.card-studio > .card-header {
  background: var(--studio-gold-soft);
  border-bottom-color: var(--studio-gold-border);
}

/* ---------------------------------------------------------------- tables
   The "reusable professional data table": consistent header treatment,
   row hover (a data table should read as scannable/interactive even
   where no row click exists), and status badges (unchanged -- already a
   consistent, correct pattern driven by each status enum's own colour). */

.table-studio thead th {
  background: var(--studio-gold-soft);
  border-bottom: 1.5px solid var(--studio-gold-border);
  font-size: var(--studio-text-label);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  color: var(--studio-ink-muted);
}

.table-studio tbody tr {
  transition: background-color .1s ease;
}
.table-studio tbody tr:hover {
  background-color: var(--studio-gold-soft);
}

/* Numbers in a table read as a column, not prose -- tabular figures so
   digits line up, already applied via .money; extended here to make it
   the rule for any numeric table cell, not just money. */
.money, td.money, th.money {
  text-align: right;
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}

/* A superseded price, shown the way the archive prints it -- #FF0000,
   verified against the run colour in the source DOCX
   (docs/ARCHIVE_ANALYSIS.md), not the grey this previously rendered as. */
.list-price {
  text-decoration: line-through;
  color: #FF0000;
  margin-right: 0.4rem;
}

/* Plain red, no strikethrough -- a payment reminder or a figure that should
   stand out ("Balance", "Total Balance"), independent of list-price above.
   Same class name/colour as the PDF stylesheet (_document_base.html) so the
   on-screen preview matches the generated document. */
.highlight-red, .highlight-red td { color: #FF0000; }

.totals-card { max-width: 26rem; margin-left: auto; }

/* Line-item editor */
#items-body tr.item-row td { vertical-align: top; }
#items-body input, #items-body textarea { font-size: 0.9rem; }

/* Template editor: each block numbered by its actual position in the
   document, computed live from DOM order so add/move/remove never needs to
   renumber anything in JS. Not Bootstrap's .badge -- an empty .badge is
   `display: none` by Bootstrap's own default (it assumes an empty badge is
   a mistake), which would hide a badge whose only content is generated
   ::before text since :empty checks real DOM children, not rendered output. */
#elements-body { counter-reset: block-index; }
.element-row { counter-increment: block-index; }
.block-index-badge {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 1.25rem;
  height: 1.25rem;
  padding: 0 .4rem;
  border-radius: 999px;
  background: var(--studio-ink);
  color: #fff;
  font-size: var(--studio-text-label);
  font-weight: 600;
}
.block-index-badge::before { content: counter(block-index); }

.htmx-request .htmx-indicator { visibility: visible; }
.htmx-indicator { visibility: hidden; }

/* -------------------------------------------------------- empty states
   One consistent look for "nothing here yet" across every list -- reused
   verbatim by quotations, invoices, templates, customers, documents. */
.studio-empty {
  text-align: center;
  padding: var(--studio-space-xl) var(--studio-space-md);
  color: var(--studio-ink-muted);
}
.studio-empty .studio-empty-title {
  font-size: var(--studio-text-section-title);
  font-weight: 600;
  color: var(--studio-ink);
  margin-bottom: var(--studio-space-xs);
}

/* --- document library ---------------------------------------------------- */

.doc-card {
  transition: box-shadow .12s ease, transform .12s ease;
}
.doc-card:hover {
  box-shadow: var(--studio-shadow-md);
  transform: translateY(-1px);
}

/* Fixed-ratio thumbnail box so the grid stays aligned whatever the page size. */
.doc-thumb {
  position: relative;
  aspect-ratio: 17 / 22;          /* US Letter */
  overflow: hidden;
  background: var(--studio-cream);
  border-bottom: 1px solid var(--studio-gold-border);
}
.doc-thumb img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: top center;
}

/* A product's own photo, not a document-page preview -- a product isn't
   Letter-shaped, and the photo should fit whole inside the tile rather
   than being cropped/zoomed to fill a page-shaped box (see .photo-tile
   above for the identical reasoning). */
.product-thumb {
  position: relative;
  aspect-ratio: 4 / 3;
  overflow: hidden;
  background: var(--studio-cream);
  border-bottom: 1px solid var(--studio-gold-border);
}
.product-thumb img {
  width: 100%;
  height: 100%;
  object-fit: contain;
}
.doc-thumb-placeholder {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 100%;
  color: var(--studio-gold);
  font-weight: 600;
  letter-spacing: .05em;
}
.doc-badge {
  position: absolute;
  top: .4rem;
  right: .4rem;
}

.extracted-text {
  white-space: pre-wrap;
  word-break: break-word;
  max-height: 22rem;
  overflow-y: auto;
  font-family: inherit;
  color: var(--studio-ink-muted);
}

/* --- upload & review ----------------------------------------------------- */

.dropzone {
  border: 2px dashed var(--studio-gold-border);
  border-radius: var(--bs-border-radius);
  padding: 2.5rem 1rem;
  text-align: center;
  background: rgba(255, 242, 204, 0.35);
  transition: background .12s ease, border-color .12s ease;
}
.dropzone.dragging {
  border-color: var(--studio-gold);
  background: rgba(255, 242, 204, 0.75);
}

.review-thumb {
  width: 90px;
  height: 116px;
  object-fit: cover;
  object-position: top center;
  border: 1px solid var(--studio-gold-border);
  border-radius: .25rem;
  background: var(--studio-cream);
}
.review-thumb-placeholder {
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--studio-gold);
  font-weight: 600;
  font-size: .8rem;
}

/* --- ONLYOFFICE editor --------------------------------------------------- */

.office-editor {
  height: calc(100vh - 16rem);
  min-height: 32rem;
  border: 1px solid var(--studio-gold-border);
  border-radius: var(--bs-border-radius-sm);
  overflow: hidden;
}

/* The editor swaps our placeholder for its own iframe; both selectors are
   needed because the element type differs between ONLYOFFICE versions. */
.office-editor > iframe,
.office-editor > div {
  width: 100%;
  height: 100%;
  border: 0;
  display: block;
}

/* --- project timeline ---------------------------------------------------- */

.timeline {
  list-style: none;
  margin: 0;
  padding: 0 0 0 2rem;
  position: relative;
}
.timeline::before {
  content: "";
  position: absolute;
  left: .65rem;
  top: .5rem;
  bottom: .5rem;
  width: 2px;
  background: var(--studio-gold-border);
}
.timeline-entry {
  position: relative;
  padding: .6rem 0;
  border-bottom: 1px solid rgba(0, 0, 0, .05);
}
.timeline-entry:last-child { border-bottom: 0; }
.timeline-marker {
  position: absolute;
  left: -2rem;
  top: .7rem;
  width: 1.5rem;
  height: 1.5rem;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  font-size: .7rem;
  padding: 0;
}

/* --- quotation product photos -------------------------------------------- */

.photo-tile img {
  width: 100%;
  aspect-ratio: 4 / 3;
  /* contain, not cover: the whole photo fits inside the tile instead of
     being cropped/zoomed to fill it -- the tile's own background shows
     through as a plain letterbox when the photo's own proportions differ. */
  object-fit: contain;
  border: 1px solid var(--studio-gold-border);
  border-radius: .25rem;
  background: var(--studio-cream);
  cursor: zoom-in;
}
.photo-tile img:focus-visible {
  outline: 2px solid var(--studio-gold);
  outline-offset: 2px;
}

/* A thumbnail at upload-form size is too small to judge before choosing
   where a photo goes -- click/Enter opens it here at real size. Native
   <dialog>, no JS library: dialog::backdrop is the browser's own modal
   layer. */
#photo-lightbox {
  border: 0;
  border-radius: .5rem;
  padding: 0;
  max-width: min(90vw, 60rem);
  max-height: 85vh;
  background: transparent;
}
#photo-lightbox::backdrop {
  background: rgba(20, 16, 8, 0.72);
}
#photo-lightbox img {
  display: block;
  max-width: min(90vw, 60rem);
  max-height: 78vh;
  border-radius: .5rem;
}
#photo-lightbox .photo-lightbox-caption {
  background: var(--studio-surface);
  padding: .5rem .75rem;
  border-radius: 0 0 .5rem .5rem;
  font-size: var(--studio-text-helper);
  color: var(--studio-ink-muted);
}

/* Inline document viewer on the record page. */
.doc-viewer {
  width: 100%;
  height: 70vh;
  min-height: 30rem;
  border: 0;
  display: block;
}

/* The Stage 5 split-screen live preview (quotations/invoices forms) is raw
   HTML in an iframe via srcdoc, not an embedded PDF file -- a real PDF
   viewer centers and letterboxes a page on its own, but plain HTML has no
   such behaviour, so without this the preview's cream background (fixed at
   the real printed page's width, from the letterhead artwork's own mm
   dimensions) stayed narrower than content that stretches to 100%, leaving
   a mismatched strip down the right side. Capping the iframe itself at the
   true page width keeps everything -- background and content alike --
   agreeing on the same width, so the preview is never wider than what
   actually prints. Toggled between portrait/landscape by JS reading the
   orientation <select> (see quotations/invoices form.html). */
.doc-viewer-live {
  width: 100%;
  max-width: 215.9mm;
  height: 70vh;
  min-height: 30rem;
  margin: 0 auto;
  border: 0;
  display: block;
  background: var(--studio-surface);
}
.doc-viewer-live.landscape { max-width: 279.4mm; }

/* ---------------------------------------------------- document creation
   Stage 4: the quotation/invoice form is one long scroll through several
   cards (Document, Line items, Specification, Adjustments, Terms, Photos).
   This is a jump-to nav for that scroll, not a wizard -- every section stays
   on the page and editable in place, so nothing about the existing HTMX
   row-editing or server-side validation changes. Sticky so it stays
   reachable no matter how far down the form the user has scrolled. */
.studio-form-nav {
  position: sticky;
  top: 0;
  z-index: 5;
  display: flex;
  flex-wrap: wrap;
  gap: .375rem;
  padding: .625rem 0;
  margin-bottom: 1rem;
  background: var(--studio-bg);
  border-bottom: 1px solid var(--studio-border);
}
.studio-form-nav a {
  display: inline-flex;
  align-items: center;
  gap: .3rem;
  padding: .3rem .75rem;
  border-radius: 999px;
  font-size: var(--studio-text-label);
  font-weight: 600;
  color: var(--studio-ink-muted);
  background: var(--studio-surface);
  border: 1px solid var(--studio-border);
  text-decoration: none;
  white-space: nowrap;
}
.studio-form-nav a:hover { color: var(--studio-ink); border-color: var(--studio-gold-border); }
.studio-form-nav a .badge { font-weight: 600; }

/* Anchor targets land clear of the sticky nav above instead of tucked
   under it. */
.studio-form-section { scroll-margin-top: 3.5rem; }

/* The "save first, then add photos" placeholder -- was a plain grey alert,
   now matches the rest of the form instead of reading as an error. */
.studio-form-placeholder {
  padding: var(--studio-space-xl) var(--studio-space-md);
  text-align: center;
  color: var(--studio-ink-muted);
  border: 1px dashed var(--studio-border);
  border-radius: .375rem;
  background: var(--studio-surface);
}

/* Skip-navigation link (docs/UI_UX_AUDIT.md: "no skip-navigation link"). Off
   -screen until keyboard-focused, standard pattern -- a mouse user never
   sees it, a keyboard user tabbing in from the address bar does. */
.studio-skip-link {
  position: absolute;
  top: -3rem;
  left: 1rem;
  z-index: 1090;
  padding: .5rem 1rem;
  background: var(--studio-ink);
  color: #fff;
  border-radius: 0 0 .375rem .375rem;
  text-decoration: none;
  transition: top .1s ease;
}
.studio-skip-link:focus {
  top: 0;
  color: #fff;
}

/* ---------------------------------------------------- quotation form steps */
.step-no {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.5rem;
  height: 1.5rem;
  margin-right: 0.4rem;
  border-radius: 50%;
  background: var(--studio-gold);
  color: #fff;
  font-size: 0.8rem;
  font-weight: 600;
}
/* Extra columns (old price, bold, red, notes, groups) stay out of the way
   until "Show extra columns" is ticked under More options. */
.studio-quote-form.compact .opt-col { display: none; }
details.card > summary { list-style: revert; }
.studio-save-bar {
  position: sticky;
  bottom: 0;
  z-index: 5;
  display: flex;
  gap: 0.5rem;
  padding: 0.75rem 0;
  background: var(--bs-body-bg, #fff);
  border-top: 1px solid var(--studio-gold-border);
}
@media (max-width: 991.98px) {
  .studio-save-bar { bottom: calc(4rem + env(safe-area-inset-bottom)); padding-inline: 0.25rem; }
}

/* ------------------------------------------------- browser-drawn surfaces */
::selection { background: rgba(224, 184, 74, 0.45); color: var(--studio-ink); }
input, textarea { caret-color: var(--studio-gold); }
:focus-visible { outline: 2px solid var(--studio-gold); outline-offset: 2px; }
.studio-sidebar :focus-visible, .studio-tabbar :focus-visible, .studio-sheet :focus-visible {
  outline-color: var(--studio-shell-gold);
}
a { text-underline-offset: 0.18em; }
html { scrollbar-color: #cfc4ad transparent; }

/* ------------------------------------------------------------ page parts */
.studio-page-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  flex-wrap: wrap;
  margin-bottom: 1.25rem;
}
.studio-page-head h1 { margin: 0; }
.studio-head-actions { gap: 0.5rem; }
.studio-head-actions .btn { display: inline-flex; align-items: center; gap: 0.35rem; }
.studio-head-actions .ico { width: 1.1rem; height: 1.1rem; }

.studio-home {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 20rem;
  gap: 1.5rem;
  align-items: start;
}
.studio-home-main, .studio-home-side { display: grid; gap: 1.5rem; min-width: 0; }
@media (max-width: 1199.98px) { .studio-home { grid-template-columns: 1fr; } }

.studio-panel {
  background: var(--studio-surface);
  border: 1px solid var(--studio-border);
  border-radius: var(--bs-border-radius-lg);
  padding: 1.1rem 1.25rem;
}
.studio-panel h2 { font-size: 1.05rem; font-weight: 650; margin: 0; }
.studio-panel-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 1rem;
  margin-bottom: 0.5rem;
}
.studio-more {
  display: inline-flex;
  align-items: center;
  gap: 0.1rem;
  font-size: 0.875rem;
  font-weight: 500;
  text-decoration: none;
  white-space: nowrap;
}
.studio-more .ico { width: 1rem; height: 1rem; }

.studio-owed-sum { margin: 0.25rem 0 0.75rem; color: var(--studio-ink-muted); }
.studio-owed-sum .money {
  display: block;
  font-size: 1.75rem;
  font-weight: 700;
  color: var(--studio-owed);
  letter-spacing: -0.01em;
  text-align: left;
}

/* A list of tappable rows -- the phone-friendly replacement for a table
   whose columns would otherwise scroll sideways. */
.studio-rows { list-style: none; margin: 0; padding: 0; }
.studio-rows > li + li { border-top: 1px solid var(--studio-border); }
.studio-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  padding: 0.75rem 0.5rem;
  margin: 0 -0.5rem;
  border-radius: var(--bs-border-radius-sm);
  color: inherit;
  text-decoration: none;
}
.studio-row:hover { background: var(--studio-gold-soft); color: inherit; }
.studio-row-main { display: grid; gap: 0.15rem; min-width: 0; flex: 1 1 auto; }
.studio-row-title { font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.studio-row-meta { font-size: 0.8125rem; color: var(--studio-ink-muted); }
.studio-row-amount { display: grid; justify-items: end; gap: 0.15rem; flex: 0 0 auto; }
.studio-row-amount .money { font-weight: 600; }
.studio-owed { color: var(--studio-owed); }

/* Paid-so-far against the total, the archive bills' Advance / Balance
   ledger as one bar. Green is money in; the track is what is left. */
.studio-ledger {
  display: block;
  height: 0.4rem;
  max-width: 16rem;
  margin: 0.3rem 0 0.1rem;
  border-radius: 1rem;
  background: var(--studio-track);
  overflow: hidden;
}
.studio-ledger-paid {
  display: block;
  height: 100%;
  min-width: 0.4rem;
  background: var(--studio-paid);
  border-radius: inherit;
}

.studio-status {
  font-size: 0.75rem;
  font-weight: 600;
  padding: 0.1rem 0.5rem;
  border-radius: 1rem;
  background: #ece7dc;
  color: #4d463b;
}
.studio-status-info { background: #e1ecf6; color: #1d4f7a; }
.studio-status-success { background: #e2f1e5; color: #22622f; }
.studio-status-warning { background: #fbefd5; color: #7a4b00; }
.studio-status-danger { background: #f8e1de; color: #9b2c22; }
.studio-status-primary { background: #f3ead2; color: #5c4600; }

.studio-drafts-link {
  display: inline-flex;
  align-items: center;
  gap: 0.1rem;
  margin-top: 0.75rem;
  font-weight: 500;
  text-decoration: none;
}
.studio-drafts-link .ico { width: 1rem; height: 1rem; }
.studio-empty-line { color: var(--studio-ink-muted); margin: 0.25rem 0 0; }

.studio-facts { margin: 0; display: grid; }
.studio-facts > div {
  display: flex;
  justify-content: space-between;
  gap: 1rem;
  padding: 0.5rem 0;
  border-top: 1px solid var(--studio-border);
}
.studio-facts > div:first-child { border-top: 0; }
.studio-facts dt { font-weight: 400; color: var(--studio-ink-muted); }
.studio-facts dd { margin: 0; font-weight: 600; font-variant-numeric: tabular-nums; }

.studio-activity { list-style: none; margin: 0; padding: 0; display: grid; gap: 0.7rem; }
.studio-activity li { display: flex; gap: 0.6rem; align-items: baseline; font-size: 0.9rem; }
.studio-dot { width: 0.5rem; height: 0.5rem; border-radius: 50%; flex: 0 0 auto; transform: translateY(-0.1rem); }
.studio-dot { background: #a99f8c; }
.studio-dot.studio-status-info { background: #3b7bb3; }
.studio-dot.studio-status-success { background: var(--studio-paid); }
.studio-dot.studio-status-warning { background: #d69a1c; }
.studio-dot.studio-status-danger { background: #c0392b; }
.studio-dot.studio-status-primary { background: var(--studio-gold); }
.studio-filters .form-control, .studio-filters .form-select { background-color: var(--studio-surface); }

/* "Next step" box on a quotation: one sentence, the buttons for it. */
.studio-next {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem 1.5rem;
  flex-wrap: wrap;
  padding: 1rem 1.25rem;
  border-radius: var(--bs-border-radius-lg);
  background: #fbf3dc;
  border: 1px solid var(--studio-gold-border);
}
.studio-next-text { margin: 0; font-weight: 500; max-width: 38rem; }
.studio-next-actions { display: flex; gap: 0.5rem; flex-wrap: wrap; }
.studio-next-actions .btn { display: inline-flex; align-items: center; gap: 0.4rem; }
@media (max-width: 575.98px) {
  .studio-next-actions, .studio-next-actions form { width: 100%; }
  .studio-next-actions .btn { width: 100%; justify-content: center; }
}

/* Quote form on a phone: details rows stack (name over a full-width box),
   and the preview is a section you tap open instead of a far-away panel. */
.studio-preview > summary { list-style: none; cursor: pointer; }
.studio-preview > summary::-webkit-details-marker { display: none; }
@media (min-width: 992px) {
  .studio-preview { position: sticky; top: 1rem; }
  .studio-preview > summary { pointer-events: none; }
}
@media (max-width: 991.98px) {
  .studio-preview-col { order: -1; }
  .studio-preview > summary::after { content: "Tap to open"; font-size: 0.8rem; font-weight: 500; color: var(--studio-gold); }
  .studio-preview[open] > summary::after { content: "Hide"; }
  #section-specification thead { display: none; }
  #specs-body tr.spec-row {
    display: grid;
    grid-template-columns: 1fr auto;
    gap: 0.35rem 0.5rem;
    padding: 0.6rem 0.75rem;
    border-bottom: 1px solid var(--studio-border);
  }
  #specs-body tr.spec-row > td { display: block; width: auto !important; padding: 0; border: 0; }
  #specs-body tr.spec-row > td:nth-child(2) { grid-column: 1 / -1; grid-row: 2; }
  #specs-body tr.spec-row > td:last-child { grid-column: 2; grid-row: 1; }
  #specs-body tr.spec-row > td.opt-col { grid-column: 1 / -1; }
  #specs-body tr.spec-row input[name$="-label"] { font-weight: 600; }
  #items-body tr.item-row { display: grid; grid-template-columns: 1fr 1fr auto; gap: 0.35rem 0.5rem; padding: 0.6rem 0.75rem; border-bottom: 1px solid var(--studio-border); }
  #items-body tr.item-row > td { display: block; width: auto !important; padding: 0; border: 0; }
  #items-body tr.item-row > td:first-child { grid-column: 1 / 3; }
  #section-price thead { display: none; }
}
@media (max-width: 991.98px) {
  #items-body tr.item-row > td:first-child { grid-column: 1 / 3; grid-row: 1; }
  #items-body tr.item-row > td:last-child { grid-column: 3; grid-row: 1; }
  #items-body tr.item-row > td:nth-child(2) { grid-column: 1; grid-row: 2; }
  #items-body tr.item-row > td:nth-child(3) { grid-column: 2 / 4; grid-row: 2; }
  #items-body tr.item-row > td:nth-child(4) { grid-column: 1; grid-row: 3; }
  #items-body tr.item-row > td:nth-child(5) { grid-column: 2 / 4; grid-row: 3; }
  #items-body tr.item-row input[name$="-quantity"]::placeholder { color: transparent; }
}
/* Must beat the phone row layout above, which sets every cell to block. */
.studio-quote-form.compact #specs-body tr > td.opt-col,
.studio-quote-form.compact #items-body tr > td.opt-col,
.studio-quote-form.compact #items-body .opt-col { display: none; }
.btn-check:checked + .btn-outline-secondary {
  background: var(--studio-gold);
  border-color: var(--studio-gold);
  color: #fff;
}

.studio-quick { display: grid; gap: 1.25rem; max-width: 46rem; }
.studio-quick textarea { font-size: 1rem; }
.studio-photo-layout { display: grid; gap: 0.25rem; margin-top: 0.4rem; }
.studio-photo-layout .form-select { font-size: 0.75rem; padding-top: 0.2rem; padding-bottom: 0.2rem; }

/* ------------------------------------------------------------- photos */
.studio-add-photos { display: inline-flex; align-items: center; gap: 0.4rem; cursor: pointer; }
.studio-photo-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(9.5rem, 1fr)); gap: 0.75rem; }
.studio-photo-grid .photo-tile img { width: 100%; aspect-ratio: 4 / 3; object-fit: cover; border-radius: var(--bs-border-radius-sm); }
.studio-photo-buttons { display: flex; gap: 0.35rem; margin-top: 0.35rem; }
.studio-photo-buttons > *, .studio-photo-buttons form .btn { flex: 1 1 0; width: 100%; }

.studio-crop { width: min(44rem, 94vw); border: 0; border-radius: var(--bs-border-radius-lg); padding: 1.25rem; }
.studio-crop::backdrop { background: rgba(20, 16, 6, 0.6); }
.studio-crop-stage { position: relative; user-select: none; touch-action: none; line-height: 0; }
.studio-crop-stage img { width: 100%; max-height: 65vh; object-fit: contain; }
.studio-crop-box {
  position: absolute;
  border: 2px solid #fff;
  box-shadow: 0 0 0 100vmax rgba(0, 0, 0, 0.45);
  cursor: move;
  touch-action: none;
}
.studio-crop-handle {
  position: absolute; right: -0.7rem; bottom: -0.7rem;
  width: 1.4rem; height: 1.4rem; border-radius: 50%;
  background: var(--studio-shell-gold); border: 2px solid #fff; cursor: nwse-resize;
}
.studio-crop-stage { overflow: hidden; }
.studio-crop-shapes { display: flex; gap: 0.4rem; flex-wrap: wrap; margin-top: 0.75rem; }

/* Preview hidden: the form takes the full width. */
@media (min-width: 992px) {
  #form-and-preview.preview-hidden > .studio-preview-col { display: none; }
  #form-and-preview.preview-hidden > .studio-form-col { flex: 0 0 100%; max-width: 62rem; }
}
/* The stage hugs the photo exactly, so box fractions are photo fractions. */
.studio-crop-stage { width: fit-content; max-width: 100%; margin: 0 auto; }
.studio-crop-stage img { display: block; width: auto; max-width: 100%; max-height: 65vh; object-fit: initial; }
.studio-crop-handle { right: 0; bottom: 0; transform: translate(35%, 35%); }
.studio-needs-fix { border-color: #c0392b; box-shadow: 0 0 0 2px rgba(192, 57, 43, 0.15); }

/* ------------------------------------------------ worst-case data fixes */
/* Names wrap (they identify the customer) but never past two lines; titles
   and long metadata are clamped, with the full text on hover. */
.studio-row-title.studio-wrap-2 { white-space: normal; }
.studio-wrap-2, .studio-clamp-2 {
  display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2;
  overflow: hidden; overflow-wrap: anywhere;
}
.studio-clamp-1 { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.studio-row-sub { font-size: 0.875rem; color: var(--studio-ink-muted); }

/* Quote details on a phone: label above value. */
.studio-details td { overflow-wrap: anywhere; vertical-align: top; }
.studio-details ul { padding-left: 1.1rem; }
@media (max-width: 575.98px) {
  .studio-details tr { display: block; padding: 0.5rem 0.75rem; border-bottom: 1px solid var(--studio-border); }
  .studio-details td { display: block; width: auto !important; padding: 0; border: 0; }
  .studio-details td.studio-details-label { font-size: 0.8125rem; font-weight: 600; color: var(--studio-ink-muted); margin-bottom: 0.15rem; }
}

/* Tables that become labelled cards on a phone (bill payments). */
@media (max-width: 575.98px) {
  .studio-stack thead { display: none; }
  .studio-stack tr { display: grid; grid-template-columns: 1fr auto; gap: 0.15rem 1rem;
                     padding: 0.6rem 0.75rem; border-bottom: 1px solid var(--studio-border); }
  .studio-stack td { display: block; padding: 0; border: 0; text-align: left; }
  .studio-stack td[data-label]::before { content: attr(data-label) ": "; color: var(--studio-ink-muted); font-weight: 400; }
  .studio-stack td.money { grid-column: 1 / -1; font-size: 1.05rem; }
  .studio-stack td:last-child:not([data-label]) { grid-column: 2; grid-row: 1; }
  .studio-stack td:empty { display: none; }
}

/* Pager: Previous / Page 3 of 52 / Next */
.studio-pager { display: flex; align-items: center; gap: 0.75rem; flex-wrap: wrap; }
.studio-pager-where { font-size: 0.875rem; color: var(--studio-ink-muted); }

/* ------------------------------------------------- accessibility pass */
/* Bootstrap's green, red and yellow fall below 4.5:1 on the cream page
   (measured 4.2 and 1.5); the same hues, darkened until they pass. */
:root { --studio-owed: #9a4315; }
.text-danger { color: #a52834 !important; }
.btn-outline-success {
  --bs-btn-color: #146c43; --bs-btn-border-color: #146c43;
  --bs-btn-hover-bg: #146c43; --bs-btn-hover-border-color: #146c43; --bs-btn-hover-color: #fff;
  --bs-btn-active-bg: #0f5132; --bs-btn-active-border-color: #0f5132;
}
.btn-outline-danger {
  --bs-btn-color: #a52834; --bs-btn-border-color: #a52834;
  --bs-btn-hover-bg: #a52834; --bs-btn-hover-border-color: #a52834; --bs-btn-hover-color: #fff;
  --bs-btn-active-bg: #842029; --bs-btn-active-border-color: #842029;
}
.btn-outline-warning {
  --bs-btn-color: #7a4b00; --bs-btn-border-color: #b07a12;
  --bs-btn-hover-bg: #b07a12; --bs-btn-hover-border-color: #b07a12; --bs-btn-hover-color: #fff;
  --bs-btn-active-bg: #8a5f0c; --bs-btn-active-border-color: #8a5f0c;
}
/* Phone: small links and tick boxes get a finger-sized target. */
@media (max-width: 991.98px) {
  .studio-more, .studio-drafts-link { min-height: 44px; padding: 0.5rem 0; }
  .form-check-input { width: 1.35em; height: 1.35em; }
}

/* Dragging photos */
#section-photos .photo-tile[draggable="true"] { cursor: grab; }
#section-photos .photo-tile.is-dragging { opacity: 0.4; }
#section-photos .photo-tile.drop-before { box-shadow: -4px 0 0 0 var(--studio-gold); }
#section-photos .photo-tile.drop-after { box-shadow: 4px 0 0 0 var(--studio-gold); }
[data-photo-drop].is-drop-target { outline: 2px dashed var(--studio-gold); outline-offset: -6px; background: var(--studio-gold-soft); }

/* ------------------------------------------------------- archive photos */
.studio-tabs { display: flex; gap: 0.25rem; border-bottom: 1px solid var(--studio-border); flex-wrap: wrap; }
.studio-tabs a { padding: 0.6rem 0.9rem; text-decoration: none; color: var(--studio-ink-muted); font-weight: 500;
                 border-bottom: 2px solid transparent; margin-bottom: -1px; }
.studio-tabs a[aria-current="page"] { color: var(--studio-ink); border-bottom-color: var(--studio-gold); }
.studio-tab-count { font-size: 0.8rem; color: var(--studio-ink-muted); margin-left: 0.2rem; }
.studio-chips { display: flex; gap: 0.4rem; flex-wrap: wrap; }
.studio-chips a { padding: 0.35rem 0.75rem; border: 1px solid var(--studio-border); border-radius: 2rem;
                  text-decoration: none; color: var(--studio-ink); font-size: 0.875rem; background: var(--studio-surface); }
.studio-chips a span { color: var(--studio-ink-muted); margin-left: 0.15rem; }
.studio-chips a.active { background: var(--studio-gold); border-color: var(--studio-gold); color: #fff; }
.studio-chips a.active span { color: #f3e7c4; }
.studio-archive-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(12rem, 1fr)); gap: 1rem; }
.studio-archive-card { background: var(--studio-surface); border: 1px solid var(--studio-border);
                       border-radius: var(--bs-border-radius-lg); overflow: hidden; display: flex; flex-direction: column; }
.studio-archive-card > img { width: 100%; aspect-ratio: 4 / 3; object-fit: cover; background: #efe9dc; cursor: zoom-in; }
.studio-archive-body { padding: 0.6rem 0.7rem 0.8rem; display: flex; flex-direction: column; flex: 1; }
.studio-archive-name { font-weight: 600; font-size: 0.925rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.studio-archive-card details > summary { list-style: none; }
.studio-archive-card details > summary::-webkit-details-marker { display: none; }
.studio-make-product { margin-top: 0.5rem; }
/* Bill / invoice item rows on a phone: same stacked card as quotation items.
   The bill table kept its column headings and had an extra "Red text" cell,
   which crushed every input into the first column (QA, November 2026). */
@media (max-width: 991.98px) {
  #section-items thead { display: none; }
  #section-items table, #section-items #items-body { display: block; width: 100%; }
  #items-body tr.item-row > td:nth-child(6) { grid-column: 1 / 3; grid-row: 4; }
  #items-body tr.item-row > td:nth-child(6)::before { content: "Red text "; font-size: 0.8125rem; color: var(--studio-ink-muted); }
  #items-body tr.item-row > td:last-child { grid-column: 3; grid-row: 1; }
  #items-body tr.item-row textarea, #items-body tr.item-row input[type=text] { width: 100%; }
}

/* ---------------------------------------------------- phone QA fixes */
@media (max-width: 575.98px) {
  .studio-stack td { overflow-wrap: anywhere; }
  .studio-stack td[colspan] { grid-column: 1 / -1; }
  .studio-stack td[colspan]::before { content: none; }
  .studio-stack .btn { min-height: 36px; }
}
/* Menus never wider than the screen (the quote "More" menu ran off at 320). */
.dropdown-menu { max-width: calc(100vw - 1.5rem); }
.dropdown-menu .dropdown-item { white-space: normal; }
/* Save bar buttons: text centred in the taller buttons. */
.studio-save-bar .btn { display: inline-flex; align-items: center; justify-content: center; }
/* The crossed-out price on screen: the archive's pure red is too faint on
   cream (3.7:1); the PDF keeps #FF0000 to match the printed archive. */
.list-price { color: #c4161c; }
/* Finger-sized targets for plain checkboxes and table links on phones. */
@media (max-width: 991.98px) {
  input[type="checkbox"]:not(.btn-check) { width: 1.3em; height: 1.3em; }
  .table a:not(.btn) { display: inline-block; padding: 0.3rem 0; }
}
