/* ---------- /pricing - device pricing reference page (iPhones for now) ----------
   Scoped to the pricing-, device-, plan-row-, compare- and storage- prefixed
   classes so nothing here bleeds into style.css/admin.css's own rules (both are
   loaded on this page too, for the shared .btn/.btn-secondary/.modal/
   .admin-hint building blocks - see pricing.html's <head> comment).

   Weight scale used throughout (kept deliberately narrow so the page
   doesn't read as "all bold" - see v5.0.2 changelog entry): 700 is
   reserved for the one headline figure (the $/mo number) so it's the
   single strongest thing on the page; 600 marks names/headers/anything
   that needs to be findable at a glance; 500 covers small UI links and
   secondary labels, which lean on size/color/spacing for hierarchy
   instead of extra boldness. */

main.pricing-main {
  /* style.css's bare `main { max-width: 720px }` is sized for the single-
     column waiting list - this page wants to use the full width of a
     desktop screen so 3-4 device cards sit side by side, rather than
     stopping at a cap well short of what's available. */
  max-width: 1800px;
  margin: 20px auto;
  padding: 0 24px 60px;
}

/* ---------- controls bar ---------- */
/* v6.2.10: .pricing-controls and the plan-price box below sit side by side
   in here, each still sized to its own content (width: fit-content) -
   margin-bottom moved here from .pricing-controls itself so the gap under
   the row is consistent whichever one wraps taller. */
.pricing-controls-row { display: flex; flex-wrap: wrap; align-items: flex-start; gap: 16px; margin-bottom: 22px; }
.pricing-controls {
  display: flex; flex-wrap: wrap; align-items: flex-end; gap: 28px;
  width: fit-content; max-width: 100%;
  padding: 16px 20px; border-radius: 14px;
  background: var(--raised); border: 1px solid var(--border);
}
.pricing-control-group { display: flex; flex-direction: column; gap: 7px; }
.pricing-control-group > label { font-size: 11.5px; font-weight: 600; color: var(--muted); text-transform: uppercase; letter-spacing: 0.05em; }
.pricing-upfront-wrap {
  display: flex; align-items: center; gap: 3px; width: 130px; height: 38px; box-sizing: border-box;
  border: 1px solid var(--border); border-radius: 9px; background: var(--surface); padding: 0 12px;
}
/* $ and the figure next to it were rendering with a visible baseline
   offset - a lighter/smaller glyph next to a bold one throws off exactly
   this kind of optical alignment. Matching weight + an explicit shared
   line-height (rather than each relying on the browser's own default,
   which differs between a <span> and an <input>) is what actually lines
   them up, not just nudging one side with a margin. */
.pricing-dollar { color: var(--muted); font-size: 15px; font-weight: 600; line-height: 1; }
#upfrontInput {
  border: none; background: transparent; color: var(--text); font-size: 16px; font-weight: 600;
  line-height: 1; width: 100%; padding: 6px 0; font-variant-numeric: tabular-nums;
  -moz-appearance: textfield;
}
#upfrontInput:focus { outline: none; }
#upfrontInput::-webkit-outer-spin-button, #upfrontInput::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
.pricing-pillrow { display: flex; align-items: center; gap: 5px; height: 38px; }

/* ---------- v6.2.10: plan-price add-on box ----------
   Deliberately its own bordered card (same treatment as .pricing-controls
   above, not a third .pricing-control-group merged into it) sitting beside
   the main controls bar - detached on purpose, see pricing.html's comment. */
.pricing-planprice-box {
  display: flex; align-items: flex-start;
  width: fit-content; max-width: 100%;
  padding: 16px 20px; border-radius: 14px;
  background: var(--raised); border: 1px solid var(--border);
}
.pricing-planprice-row { display: flex; align-items: center; gap: 10px; height: 38px; }
.pricing-planprice-amount-wrap {
  display: flex; align-items: center; gap: 3px; width: 100px; height: 38px; box-sizing: border-box;
  border: 1px solid var(--border); border-radius: 9px; background: var(--surface); padding: 0 12px;
}
.pricing-planprice-amount-wrap.hidden { display: none; }
/* Same input treatment as #upfrontInput just above - "should behave like
   everything else on this page" - no native spin buttons, no visible
   border of its own (the wrap around it draws that), same tabular-nums
   figure weight. */
#planPriceInput {
  border: none; background: transparent; color: var(--text); font-size: 16px; font-weight: 600;
  line-height: 1; width: 100%; padding: 6px 0; font-variant-numeric: tabular-nums;
  -moz-appearance: textfield;
}
#planPriceInput:focus { outline: none; }
#planPriceInput::-webkit-outer-spin-button, #planPriceInput::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
.pricing-planprice-suffix { color: var(--muted); font-size: 12px; white-space: nowrap; }
.pricing-pill {
  appearance: none; -webkit-appearance: none; -moz-appearance: none;
  height: 100%; box-sizing: border-box; display: inline-flex; align-items: center;
  padding: 0 14px; border-radius: 999px; border: 1px solid var(--border); background: var(--surface);
  color: var(--muted); font-size: 13px; font-weight: 500; cursor: pointer;
}
.pricing-pill.active { background: var(--blue); border-color: var(--blue); color: #fff; }
.pricing-reset-link {
  height: 38px; display: inline-flex; align-items: center;
  background: none; border: none; color: var(--muted);
  font-size: 12.5px; font-weight: 500; cursor: pointer; text-decoration: underline; text-underline-offset: 2px;
}
.pricing-reset-link:hover { color: var(--blue); }

.pricing-theme-toggle { margin-left: 6px; font-size: 16px; line-height: 1; }

/* ---------- device grid + cards ---------- */
/* #deviceGrid itself is just a plain vertical stack now (v5.0.7) - the
   default group's devices sit in their own nested .device-grid, and each
   named section gets its own .device-grid too (see .pricing-section-body
   below), so every group lays out its own independent up-to-4-columns
   grid rather than one grid spanning the whole board. */
#deviceGrid { display: flex; flex-direction: column; gap: 30px; }
#deviceGrid.hidden { display: none; }
/* Capped at 4 columns max, however wide the screen gets - the minmax
   floor is whichever is bigger: 300px, or a quarter of the row (minus
   the 3 gaps between 4 columns). On an ultra-wide monitor that quarter
   exceeds 300px, so a 5th column can never fit; on a narrower screen it
   falls back below 300px and auto-fit wraps down to fewer columns as
   normal. */
.device-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(max(300px, (100% - 3 * 20px) / 4), 1fr)); gap: 20px; }

/* ---------- named sections (v5.0.7) ---------- */
/* The default (unnamed) group has no header at all - its devices just sit
   directly in the first .device-grid above, exactly like every device did
   before sections existed. A named section gets a clickable header bar;
   collapsed by default on every page load/refresh (nothing here is
   persisted - see pricing.js's expandedSections), expand state is purely
   in-memory for that visit. */
.pricing-section-header {
  width: 100%; display: flex; align-items: center; gap: 9px;
  padding: 11px 16px; border-radius: 11px; border: 1px solid var(--border);
  background: var(--raised); color: var(--text); font-size: 13.5px; font-weight: 600;
  cursor: pointer; text-align: left;
}
.pricing-section-header:hover { background: var(--hover-tint); }
.pricing-section-header .chev { font-size: 10px; color: var(--muted); transition: transform 0.15s ease; flex-shrink: 0; }
.pricing-section.open .pricing-section-header .chev { transform: rotate(180deg); }
.pricing-section-name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pricing-section-count {
  font-size: 11px; font-weight: 500; color: var(--muted); background: var(--surface);
  padding: 2px 9px; border-radius: 999px; flex-shrink: 0; font-variant-numeric: tabular-nums;
}
.pricing-section-body { margin-top: 18px; }
.pricing-section-body.hidden { display: none; }
.device-card { display: flex; flex-direction: column; border: 1px solid var(--border); border-radius: 14px; background: var(--raised); padding: 18px 20px 16px; }
.device-card-head { border-bottom: 1px solid var(--border); padding-bottom: 12px; margin-bottom: 4px; }
.device-name { margin: 0; font-size: 17.5px; font-weight: 600; letter-spacing: -0.01em; }
.device-rrp { margin: 3px 0 0; font-size: 12.5px; color: var(--muted); font-variant-numeric: tabular-nums; }

/* storage pill selector */
.storage-row { display: flex; gap: 6px; flex-wrap: wrap; margin: 10px 0 2px; }
.storage-row.hidden { display: none; }
.storage-row button {
  /* appearance:none - without it, some browsers keep rendering a button's
     own native widget chrome (particularly its background) underneath
     custom styling, which is what made the selected pill above read as
     barely-there in some cases; this makes the background below fully
     ours to control. */
  appearance: none; -webkit-appearance: none; -moz-appearance: none;
  padding: 5px 11px; border-radius: 7px; border: 1px solid var(--border); background: var(--surface);
  color: var(--muted); font-size: 12px; font-weight: 500; cursor: pointer; font-variant-numeric: tabular-nums;
}
/* Same blue used for the selected IFP-term pill above - a stronger, more
   consistent "this one's selected" signal across light/dark/any monitor
   than the previous dark-grey/black fill, which read as too subtle for
   some. */
.storage-row button.active { background: var(--blue); border-color: var(--blue); color: #fff; }

/* plan rows/blocks - each plan option is its own self-contained block:
   a header line (label (+promo end date, tiers only) on the left,
   headline $/month on the right), plus its own "Calculation" disclosure
   directly underneath - deliberately never merged into one shared table,
   so the vertical working-out for a plan always sits right under that
   same plan's own row, not detached below every other plan's numbers. */
.plan-rows { display: flex; flex-direction: column; }
.plan-block { border-top: 1px solid var(--border); padding: 11px 0; }
.plan-block:first-child { border-top: none; }
.plan-row { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
.plan-row-left { min-width: 0; }
.plan-row-label { font-size: 14px; font-weight: 600; }
/* v6.2.13: wraps the end-date text and the discount-total badge together so
   they sit on one line, in "cost · end date" order - the discount is the
   more useful fact at a glance, so it leads. */
.plan-row-meta { display: flex; align-items: center; gap: 5px; margin-top: 2px; }
/* A drawn dot rather than a "·" character - a middot glyph sits oddly high
   and reads as barely-there at this text size no matter how large the font
   is pushed; a plain circle is reliably visible and centres itself cleanly
   between the two pieces of text either side of it. */
.plan-row-meta-sep { width: 3px; height: 3px; border-radius: 50%; background: var(--muted); flex-shrink: 0; }
.plan-row-meta-sep.hidden { display: none; }
.plan-row-end { font-size: 10.5px; font-weight: 500; color: var(--orange); }
.plan-row-end.hidden { display: none; }
.plan-row-end.expired { color: var(--red); }
/* Same gold as .plan-row-end above, deliberately - not blue/purple like the
   rest of this page's accent colour, so it doesn't compete with the big
   monthly figure for attention and instead reads as one family with the
   end-date text right next to it. */
.plan-row-discount-badge { font-size: 10.5px; font-weight: 600; color: var(--orange); }
.plan-row-discount-badge.hidden { display: none; }
.plan-row-right { text-align: right; flex-shrink: 0; }
.plan-row-monthly { font-size: 21px; font-weight: 700; color: var(--blue); font-variant-numeric: tabular-nums; }
.plan-row-monthly span:last-child { font-size: 11px; font-weight: 500; color: var(--muted); margin-left: 2px; }
.plan-row-caption { font-size: 11px; color: var(--muted); margin-top: 1px; font-variant-numeric: tabular-nums; }

.plan-calc-toggle {
  margin-top: 8px; background: none; border: none; padding: 0; color: var(--muted); font-size: 11.5px;
  font-weight: 500; cursor: pointer; display: flex; align-items: center; gap: 4px;
}
.plan-calc-toggle .chev { font-size: 9px; transition: transform 0.15s ease; }
.plan-calc-toggle.open .chev { transform: rotate(180deg); }
.plan-calc-detail { margin-top: 8px; padding: 10px 12px; border-radius: 8px; background: var(--surface); }
.plan-calc-detail.hidden { display: none; }
.iph-line { display: flex; justify-content: space-between; font-size: 12.5px; padding: 2px 0; font-variant-numeric: tabular-nums; }
.iph-line-neg span:last-child { color: var(--red); }
.iph-line-total { border-top: 1px solid var(--border); margin-top: 4px; padding-top: 5px; font-weight: 600; }

/* v6.2.13: Device/Discount/+Plan price/Total per month - flat, same
   treatment as RRP/Upfront/Charged to account above (no divider or
   indentation - v6.2.12's nested "Monthly total" build-up is gone, this
   reads as one continuous list again). .calc-extra-line covers the two
   lines shown whenever there's anything beyond the flat Charged to account
   figure to explain (a discount, a plan price, or both); .calc-discount-line
   and .calc-planprice-line each toggle independently since either can be
   active without the other.
   Bug fixed here at the same time: none of these three classes previously
   had a `.hidden` rule of its own (nor did the v6.2.12 divider/indent
   classes they replaced) - .hidden did nothing, so every device's
   Calculation panel showed blank "Device"/"+ Plan price"/"Total" rows even
   with no discount and no plan price active. Same failure mode already
   documented in style.css for #pricingShortcutBtn - a class with no
   matching selector silently does nothing. */
.calc-extra-line.hidden { display: none; }
.calc-discount-line.hidden { display: none; }
.calc-planprice-line.hidden { display: none; }

/* v5.0.9: an upfront payment high enough to leave less than $199 owing -
   never hidden or blocked (a too-high upfront can still be a deliberate
   comparison against a pricier device on the same board), just flagged in
   red wherever that plan option's figures show up. */
.plan-block.below-min .plan-row-monthly-amt,
.plan-block.below-min .plan-row-monthly span:last-child,
.plan-block.below-min .plan-row-caption { color: var(--red); }
.plan-block.below-min .iph-line-total span:last-child { color: var(--red); }

/* "Compare storage options" - pops open inline below the plan list,
   matching the pill row above it (storage as columns, not rows). */
.compare-toggle {
  margin-top: 12px; padding-top: 10px; border-top: 1px dashed var(--border); background: none; border-left: none; border-right: none; border-bottom-width: 0;
  color: var(--muted); font-size: 12px; font-weight: 500; cursor: pointer; text-align: left; display: flex; align-items: center; gap: 5px;
}
.compare-toggle.hidden { display: none; }
.compare-toggle .chev { transition: transform 0.15s ease; flex-shrink: 0; }
.compare-toggle.open .chev { transform: rotate(180deg); }
.compare-table-wrap.hidden { display: none; }
.compare-table-wrap { margin-top: 10px; overflow-x: auto; }

/* the small breakdown/compare tables themselves - shared look */
.iph-table { width: 100%; border-collapse: collapse; font-variant-numeric: tabular-nums; }
.iph-table th, .iph-table td { padding: 6px 8px; font-size: 12.5px; text-align: right; white-space: nowrap; }
.iph-table th:first-child, .iph-table td:first-child { text-align: left; color: var(--muted); font-weight: 500; padding-left: 0; white-space: normal; }
.iph-table thead th { font-size: 11px; font-weight: 600; color: var(--text); border-bottom: 1px solid var(--border); padding-bottom: 8px; vertical-align: bottom; }
.iph-table thead .col-sub { display: block; font-size: 10px; font-weight: 500; color: var(--muted); margin-top: 2px; }
.iph-table td.iph-monthly-cell { font-size: 14px; font-weight: 600; color: var(--blue); }
/* v5.0.10: --detail-tint (used here up through v5.0.9) is deliberately
   very subtle - fine for the admin panel's expanded rows, but in light
   mode it read as barely-there here, making it hard to tell which
   storage column is the currently-selected one at a glance. --hover-tint
   is the same purple family at real, already-proven contrast (it's what
   this same page uses for its own hover states elsewhere), so the
   selected column reuses it instead; the header's own bottom border is
   also bumped to a solid blue rule so the column reads as "selected",
   not just "hovered". */
.iph-table th.current-col, .iph-table td.current-col { background: var(--hover-tint); }
.iph-table th.current-col { color: var(--blue); border-bottom: 2px solid var(--blue); }
.iph-table .row-promo-end { display: block; font-size: 10px; font-weight: 500; color: var(--orange); }
.iph-table .row-promo-end.expired { color: var(--red); }
.iph-table td.iph-monthly-cell.below-min { color: var(--red); font-size: 11.5px; font-weight: 600; }

/* ---------- empty state ---------- */
.pricing-empty { text-align: center; padding: 50px 20px; color: var(--muted); }
#emptyState.hidden { display: none; }
.pricing-empty p { margin: 0 0 14px; font-size: 14.5px; }

.pricing-disclosure { margin: 30px 0 0; font-size: 11.5px; color: var(--muted); text-align: center; }

/* ---------- print-select modal (reuses style.css's plain .modal) ---------- */
/* Wider than the base .modal's 340px (sized for short login-style
   dialogs) - wide enough that a device's storage options can wrap across
   the row instead of stacking one per line, which used the modal's
   available width far better than a single narrow column ever could. */
.pricing-print-modal { text-align: left; max-width: 640px; }
.pricing-print-modal h2 { text-align: center; }
.pricing-print-list { display: flex; flex-direction: column; gap: 4px; margin-bottom: 16px; max-height: 55vh; overflow-y: auto; padding-right: 2px; }
.pricing-print-group { margin-top: 12px; }
.pricing-print-group:first-child { margin-top: 0; }
.pricing-print-group-label { font-size: 13px; font-weight: 600; margin-bottom: 7px; }
/* Each option (a storage, or a whole single-storage device) is its own
   clickable chip, and they wrap left-to-right rather than stacking - a
   device with 2-4 storages now reads as one compact row instead of a
   whole column. Bigger checkbox + padding than before, specifically so
   each option is an easy target to click, not just its tiny checkbox. */
.pricing-print-options { display: flex; flex-wrap: wrap; gap: 8px 10px; }
.pricing-print-options-standalone { margin-top: 12px; }
.pricing-print-row, .pricing-print-row-sub {
  display: flex; align-items: center; gap: 9px; flex: 0 0 auto;
  padding: 8px 13px; border-radius: 9px; border: 1px solid var(--border); background: var(--surface);
  font-size: 14.5px; color: var(--text); cursor: pointer;
}
.pricing-print-row:hover, .pricing-print-row-sub:hover { background: var(--hover-tint); border-color: var(--muted); }
.pricing-print-row-sub { font-size: 13.5px; color: var(--muted); }
.pricing-print-row input, .pricing-print-row-sub input {
  width: 17px; height: 17px; margin: 0; flex-shrink: 0; accent-color: var(--blue); cursor: pointer;
}
.pricing-print-footer { display: flex; gap: 10px; }
.pricing-print-footer button { flex: 1; width: auto; margin-top: 0; }
/* .modal button's own default (style.css) makes every plain <button> in
   here solid blue, .btn-secondary or not - a same-specificity clash this
   page's Cancel button was quietly losing. This is scoped and specific
   enough to actually win, so Cancel reads as the secondary action it is
   and Print (still a plain, unclassed button) keeps the primary blue. */
#printModalOverlay .btn-secondary { background: var(--surface); color: var(--text); }
#printModalOverlay .btn-secondary:hover { background: var(--hover-tint); }

/* ---------- edit catalog drawer ---------- */
.pricing-warning { font-size: 12px; color: var(--orange); margin: 0; line-height: 1.4; }
.pricing-edit-overlay { position: fixed; inset: 0; background: rgba(15, 18, 26, 0.4); display: none; z-index: 48; }
.pricing-edit-overlay.visible { display: block; }
.pricing-edit-panel {
  position: fixed; top: 0; right: 0; bottom: 0; width: 760px; max-width: 94vw;
  background: var(--raised); box-shadow: -8px 0 24px rgba(0,0,0,0.15);
  transform: translateX(100%); transition: transform 0.25s ease; z-index: 49;
  padding: 20px; display: flex; flex-direction: column;
}
.pricing-edit-panel.open { transform: translateX(0); }
.pricing-edit-header { display: flex; align-items: center; justify-content: space-between; }
.pricing-edit-header h2 { margin: 0; font-size: 17px; }
.pricing-edit-list { flex: 1; min-height: 0; overflow-y: auto; margin: 10px 0; padding-right: 4px; }
#addDeviceBtn { flex-shrink: 0; }
.pricing-edit-error { margin: 8px 0 0; }
.pricing-edit-error.hidden { display: none; }
.pricing-edit-footer { display: flex; gap: 10px; padding-top: 14px; margin-top: 10px; border-top: 1px solid var(--border); flex-shrink: 0; }
.pricing-edit-footer .btn, .pricing-edit-footer .btn-secondary { flex: 1; width: auto; margin-top: 0; }

/* margin-bottom removed (v5.0.7) - spacing between rows now comes from
   .pricing-edit-section-devices' own flex gap, since a device row can sit
   inside the default group or any named section's list. */
.pricing-edit-device { border: 1px solid var(--border); border-radius: 10px; background: var(--surface); padding: 12px; margin-bottom: 10px; }
.pricing-edit-device:last-child { margin-bottom: 0; }
.pricing-edit-device-head { display: flex; gap: 8px; align-items: center; margin-bottom: 6px; }
/* v5.0.8: bigger glyph, a real padded hit-box, and a hover highlight - the
   previous plain small ":: " was easy to miss as something you could even
   grab. touch-action:none matches the main board's own .drag-handle, so a
   touch-drag isn't fought by the page trying to scroll at the same time. */
.pricing-edit-drag-handle {
  flex-shrink: 0; cursor: grab; color: var(--muted); font-size: 19px; line-height: 1;
  padding: 6px 5px; border-radius: 6px; user-select: none; letter-spacing: -2px;
  touch-action: none;
}
.pricing-edit-drag-handle:hover { background: var(--hover-tint); color: var(--text); }
.pricing-edit-drag-handle:active { cursor: grabbing; }
.pricing-edit-name { flex: 1; padding: 8px 10px; border: 1px solid var(--border); border-radius: 8px; background: var(--raised); color: var(--text); font-size: 14px; font-weight: 500; }
.pricing-duplicate-device {
  flex-shrink: 0; padding: 0 10px; height: 34px; border: 1px solid var(--border); border-radius: 7px;
  background: var(--icon-btn-bg); color: var(--text); font-size: 12.5px; font-weight: 500; cursor: pointer;
}
.pricing-duplicate-device:hover { background: var(--hover-tint); }
.pricing-remove-btn { flex-shrink: 0; width: 26px; height: 26px; padding: 0; border: none; border-radius: 7px; background: var(--danger-bg); color: var(--red); font-size: 15px; line-height: 1; cursor: pointer; }
.pricing-remove-btn:hover { background: var(--danger-bg-hover); }
.pricing-edit-subhead { font-size: 11px; font-weight: 600; color: var(--muted); text-transform: uppercase; letter-spacing: 0.04em; margin: 12px 0 6px; }
.pricing-edit-subhead-note { text-transform: none; font-weight: 400; letter-spacing: 0; }

/* Spacing between rows is margin (not flex gap) specifically so a row's
   own exit animation (see .pricing-row-exit) can collapse that space too,
   rather than the gap sitting there fixed while the row itself shrinks. */
.pricing-edit-storages, .pricing-edit-tiers { display: flex; flex-direction: column; }
.pricing-edit-storage { display: flex; gap: 8px; align-items: center; margin-bottom: 6px; }
.pricing-edit-storage:last-child { margin-bottom: 0; }
/* A tier is a small column now (v5.0.7), not a flat row - its normal
   fields sit in their own row (.pricing-edit-tier-row, styled exactly like
   the old flat layout), with the per-IFP-term checkboxes on a second line
   underneath. */
.pricing-edit-tier { display: flex; flex-direction: column; gap: 6px; margin-bottom: 6px; }
.pricing-edit-tier:last-child { margin-bottom: 0; }
.pricing-edit-tier-row { display: flex; gap: 8px; align-items: center; }
.pricing-edit-tier-months { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; padding-left: 2px; }
.pricing-edit-tier-months-label { font-size: 11px; color: var(--muted); margin-right: 2px; }
.pricing-edit-tier-month-label { display: flex; align-items: center; gap: 4px; font-size: 11.5px; color: var(--muted); cursor: pointer; white-space: nowrap; }
.pricing-edit-tier-month-label input { margin: 0; }
.pricing-edit-storage-label {
  flex: 0 1 120px; min-width: 70px; padding: 7px 9px; border: 1px solid var(--border); border-radius: 7px;
  background: var(--raised); color: var(--text); font-size: 13px;
}
/* Grows to fill the row - same idea as the device name field above it, so
   a tier row ends up the same overall width as the name/duplicate/remove
   row rather than stopping short with dead space on the right. */
.pricing-edit-tier-label {
  flex: 1; min-width: 90px; padding: 7px 9px; border: 1px solid var(--border); border-radius: 7px;
  background: var(--raised); color: var(--text); font-size: 13px;
}
.pricing-edit-storage-rrp-label, .pricing-edit-tier-discount-label, .pricing-edit-tier-end-label {
  display: flex; align-items: center; gap: 4px; font-size: 12px; color: var(--muted); white-space: nowrap; flex-shrink: 0;
}
.pricing-edit-storage-rrp { width: 120px; padding: 7px 8px; border: 1px solid var(--border); border-radius: 7px; background: var(--raised); color: var(--text); font-size: 13px; }
.pricing-edit-tier-discount { width: 68px; flex-shrink: 0; padding: 7px 8px; border: 1px solid var(--border); border-radius: 7px; background: var(--raised); color: var(--text); font-size: 13px; }
/* Plain numeric text boxes - the native up/down steppers add nothing here
   (nobody increments a price one dollar at a time by clicking an arrow)
   and just eat into already-tight row width. */
.pricing-edit-storage-rrp, .pricing-edit-tier-discount { -moz-appearance: textfield; }
.pricing-edit-storage-rrp::-webkit-outer-spin-button, .pricing-edit-storage-rrp::-webkit-inner-spin-button,
.pricing-edit-tier-discount::-webkit-outer-spin-button, .pricing-edit-tier-discount::-webkit-inner-spin-button {
  -webkit-appearance: none; margin: 0;
}
.pricing-edit-tier-end { padding: 6px 6px; border: 1px solid var(--border); border-radius: 7px; background: var(--raised); color: var(--text); font-size: 12.5px; width: 132px; }
.add-row-btn.pricing-add-storage, .add-row-btn.pricing-add-tier { margin-top: 6px; padding: 7px; font-size: 12.5px; }

.pricing-archived-toggle {
  margin-top: 12px; background: none; border: none; padding: 4px 0; color: var(--muted); font-size: 12px;
  font-weight: 500; cursor: pointer; text-align: left;
}
.pricing-archived-tiers { margin-top: 6px; opacity: 0.75; }
.pricing-archived-tiers.hidden { display: none; }
.pricing-archived-tag { font-size: 10.5px; font-weight: 600; color: var(--red); margin-left: 4px; white-space: nowrap; }

/* ---------- catalog sections (v5.0.7) ---------- */
/* The default (unnamed, un-removable, always-visible-on-the-board) group -
   just a small caption above its device list, no other chrome, since it
   can't be renamed/collapsed/deleted like the named ones below it. */
.pricing-edit-default-section { margin-bottom: 16px; }
.pricing-edit-default-label {
  font-size: 11px; font-weight: 600; color: var(--muted); text-transform: uppercase;
  letter-spacing: 0.04em; margin-bottom: 8px;
}
.pricing-edit-section {
  border: 1px solid var(--border); border-radius: 10px; background: var(--surface);
  padding: 10px 12px; margin-bottom: 14px;
}
.pricing-edit-section:last-child { margin-bottom: 0; }
.pricing-edit-section-head { display: flex; align-items: center; gap: 6px; }
.pricing-edit-section-toggle {
  flex-shrink: 0; width: 24px; height: 24px; padding: 0; border: none; background: none; cursor: pointer;
  display: flex; align-items: center; justify-content: center; color: var(--muted);
}
.pricing-edit-section-toggle .chev { font-size: 10px; transition: transform 0.15s ease; }
.pricing-edit-section-toggle.open .chev { transform: rotate(180deg); }
.pricing-edit-section-name {
  flex: 1; min-width: 60px; padding: 7px 9px; border: 1px solid var(--border); border-radius: 7px;
  background: var(--raised); color: var(--text); font-size: 13.5px; font-weight: 500;
}
.pricing-edit-section-count { font-size: 11.5px; color: var(--muted); flex-shrink: 0; white-space: nowrap; font-variant-numeric: tabular-nums; }
.pricing-edit-section-devices { display: flex; flex-direction: column; margin-top: 10px; min-height: 8px; }
.pricing-edit-section-devices.hidden { display: none; }
.pricing-edit-default-section .pricing-edit-section-devices { margin-top: 0; }
.pricing-add-device-to-section { margin-top: 8px; padding: 7px; font-size: 12.5px; }
/* v5.0.8: a collapsed section's own "+ Add device" only makes sense once
   you can actually see what you're adding to - hidden along with the
   device list itself, not shown floating below a closed section. */
.pricing-add-device-to-section.hidden { display: none; }
.pricing-add-section-btn { margin-top: 4px; flex-shrink: 0; }

/* ---------- drag-and-drop feedback (SortableJS, v5.0.8) ---------- */
/* Sortable applies these three classes itself during a drag - ghost is the
   placeholder left behind at the drop spot, chosen is the item actually
   being carried, drag is (mouse mode only) the element following the
   cursor. Styled here rather than left at Sortable's own bare defaults so
   a drag reads clearly against this page's cards/rows. */
.sortable-ghost { opacity: 0.35; }
.pricing-edit-device.sortable-chosen, .pricing-edit-section.sortable-chosen,
.pricing-edit-storage.sortable-chosen, .pricing-edit-tier.sortable-chosen {
  box-shadow: 0 0 0 2px var(--blue); cursor: grabbing;
}
/* v5.0.10: dragging now runs in Sortable's simulated (mouse-based) mode
   rather than native HTML5 drag-and-drop (see EDIT_DRAG_AUTOSCROLL), so
   .sortable-drag - the floating clone that actually follows the cursor -
   is now what a drag visibly looks like, not just a fallback for the odd
   browser. Gets its own lifted-card treatment rather than looking like a
   plain untouched row floating around. */
.sortable-drag { box-shadow: 0 6px 16px rgba(0, 0, 0, 0.22), 0 0 0 2px var(--blue); border-radius: 8px; cursor: grabbing; background: var(--raised); }
/* An empty section's own drop target still needs to read as "you can let
   go here" even though it has no rows to show the usual ghost highlight
   on - the dashed outline appears on the whole (empty) list. */
.pricing-edit-section-devices:empty { outline: 2px dashed transparent; outline-offset: -1px; border-radius: 8px; transition: outline-color 0.15s ease; }
body.pricing-device-dragging .pricing-edit-section-devices:empty { outline-color: var(--border); }

/* ---------- add/remove row animation (v5.0.8) ---------- */
/* A row popping in/out of existence instantly read as a jarring jump (add)
   or was easy to miss entirely (remove, especially further down a long
   list) - both now ease in/out instead of snapping. Applied as a
   short-lived class from pricing.js, not a permanent one. */
.pricing-row-enter { animation: pricingRowEnter 0.22s ease-out; }
@keyframes pricingRowEnter {
  from { opacity: 0; transform: translateY(-6px) scale(0.98); }
  to { opacity: 1; transform: none; }
}
/* pricing.js sets the explicit starting max-height/margin/padding inline
   (its own current values) right before adding this class, then flips
   them to 0 a frame later - this class only supplies the transition
   itself and the fade, never the end values, so there's nothing here for
   an !important fight with the inline styles doing the actual animating. */
.pricing-row-exit {
  overflow: hidden; opacity: 0; transform: scale(0.98);
  transition: opacity 0.16s ease, transform 0.16s ease, max-height 0.18s ease 0.02s,
    margin-top 0.18s ease 0.02s, margin-bottom 0.18s ease 0.02s,
    padding-top 0.18s ease 0.02s, padding-bottom 0.18s ease 0.02s;
}

@media (max-width: 480px) {
  .pricing-controls { gap: 16px; padding: 14px; }
  .iph-table th, .iph-table td { padding: 5px 5px; font-size: 11.5px; }
}

/* v6.0.1: same press feedback the rest of the site gained, for the controls
   this page styles itself (the header actions, the edit panel's add/remove
   buttons and the storage/term pills). */
.pricing-pill,
.pricing-remove-btn,
.pricing-add-storage,
.pricing-add-tier,
.pricing-add-device-to-section {
  transition: background-color .14s ease, border-color .14s ease,
              color .14s ease, transform .1s cubic-bezier(.2, .7, .3, 1);
  -webkit-tap-highlight-color: transparent;
}
.pricing-pill:active,
.pricing-remove-btn:active,
.pricing-add-storage:active,
.pricing-add-tier:active,
.pricing-add-device-to-section:active { transform: scale(.955); }

/* A device card is the unit you scan down the page, so it gets a hover that
   says "this is a thing" without implying the whole card is clickable. */
.device-card { transition: box-shadow .16s ease, border-color .16s ease; }
.device-card:hover { box-shadow: 0 4px 14px -4px rgba(16, 18, 28, .14); }

/* ---------- v6.1.4: Edit catalogue as a full page on a phone ----------
   This drawer's 94vw-wide slide-in panel works fine on a desktop/tablet
   where there is width to spare, but a device row needs a name field, a
   Duplicate button and a remove button on one line, and a promo row needs
   a label, a discount, a date and a remove button on another - at a
   phone's ~370px of usable width (panel padding included) that combination
   simply does not fit at a readable size, which is what was clipping
   "Duplicate" and the date field off the edge of the screen entirely.
   Two changes, together: the panel itself goes edge-to-edge instead of
   a 94vw drawer (there is no page showing behind it to justify holding
   width back), and every row in it is allowed to wrap - each field keeps
   a legible width and, where a full row still cannot fit, its overflow
   moves to a second line instead of running off-screen with no way to
   reach it. Text inputs are exempt from any font-size drop here: the
   16px floor set globally for coarse pointers (see style.css) prevents
   iOS's unrecoverable zoom-on-focus, and nothing below narrows that. */
@media (max-width: 700px) {
  .pricing-edit-panel {
    width: 100vw;
    max-width: 100vw;
    padding: 12px 10px;
    box-shadow: none;
  }
  .pricing-edit-header h2 { font-size: 16px; }
  .pricing-edit-device { padding: 10px 8px; }

  .pricing-edit-device-head,
  .pricing-edit-storage,
  .pricing-edit-tier-row { flex-wrap: wrap; row-gap: 6px; gap: 6px; }

  /* The device name and storage label both fit comfortably on their row
     once allowed to shrink from nothing (flex-basis 0) rather than from
     an unconstrained input's own ~180px browser-default minimum, which is
     what was forcing Duplicate and Remove onto their own line even though
     there was room. The promo label doesn't have that room to spare once
     the discount/date pair are counted, so it keeps first claim on its
     row instead - everything else in that row wraps under it. */
  .pricing-edit-name { flex: 1 1 0%; min-width: 0; }
  .pricing-edit-tier-label { flex: 1 1 100%; min-width: 0; }
  .pricing-edit-storage-label { flex: 1 1 90px; min-width: 50px; }
  .pricing-edit-storage-rrp { width: 84px; }
  .pricing-edit-tier-discount { width: 62px; }
  .pricing-edit-tier-end { width: 140px; }

  .pricing-duplicate-device { padding: 0 8px; font-size: 12px; }
  .pricing-edit-tier-months { gap: 8px 10px; }
  .pricing-edit-tier-month-label { font-size: 11px; }

  /* 26px was fine for a mouse pointer; a phone gets a more forgiving touch
     target without eating into row width the way growing it visually
     would - kept to 3px (half the 6px gap these rows use) so it can never
     overlap into whatever field sits right next to it. */
  .pricing-remove-btn { position: relative; }
  .pricing-remove-btn::after { content: ''; position: absolute; inset: -3px; }
}

@media (prefers-reduced-motion: reduce) {
  .pricing-pill, .pricing-remove-btn, .pricing-add-storage,
  .pricing-add-tier, .pricing-add-device-to-section,
  .device-card { transition: none; }
  .pricing-pill:active, .pricing-remove-btn:active, .pricing-add-storage:active,
  .pricing-add-tier:active, .pricing-add-device-to-section:active { transform: none; }
}
