
  .pcats{max-width:var(--px-cw,820px);margin:26px auto 0;padding:0 20px}
  .pca-left{margin-left:0;margin-right:auto}.pca-left .pcats-t{text-align:left}
  .pca-right{margin-left:auto;margin-right:0}.pca-right .pcats-t{text-align:right}
  .pcats-t{text-align:center;font-size:12px;font-weight:800;color:var(--ink-2);text-transform:uppercase;letter-spacing:.6px;margin-bottom:16px}
  /* auto-FIT, not auto-FILL. auto-fill keeps generating empty tracks to fill the
     container, so four cards in a wide column sat in the first four of six
     tracks and the row read as left-aligned — and the align setting could not
     fix it, because the tracks already spanned the full width. auto-fit
     collapses the empty tracks, and justify-content then honours the setting.
     The 232px cap stops four cards stretching into billboards on a wide page. */
  .pcats-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(158px,232px));gap:14px;justify-content:center}
  .pca-left .pcats-grid{justify-content:start}
  .pca-right .pcats-grid{justify-content:end}
  .pcat{display:flex;flex-direction:column;align-items:center;gap:12px;padding:24px 14px;background:var(--card);border:1px solid var(--line);border-radius:16px;text-decoration:none;transition:.18s cubic-bezier(.2,.7,.3,1);box-shadow:0 1px 2px rgba(15,23,42,.04)}
  .pcat:hover{border-color:color-mix(in srgb,var(--accent) 55%, var(--line));transform:translateY(-3px);box-shadow:0 16px 32px -10px color-mix(in srgb,var(--accent) 30%, transparent)}
  .pcat-ic{font-size:26px;width:52px;height:52px;display:flex;align-items:center;justify-content:center;border-radius:14px;background:color-mix(in srgb,var(--accent) 12%, var(--card));line-height:1}
  .pcat:hover .pcat-ic{background:color-mix(in srgb,var(--accent) 20%, var(--card))}
  .pcat-l{font-size:13.5px;font-weight:700;color:var(--ink);text-align:center}
  /* Cards align on a ROW, not on their own content: the icon block is fixed, the
     label sits directly under it, and the description takes the remaining space.
     Without this a one-line description and a two-line one pushed their cards to
     different heights and nothing lined up across the row. */
  .pcats-grid{align-items:stretch}
  .pcat{height:100%;justify-content:flex-start;gap:10px}
  .pcat-ic{flex:none}
  .pcat-l{margin-top:2px}
  .pcat-d{font-size:12.5px;line-height:1.5;color:var(--ink-3);text-align:center;margin-top:auto;padding-top:6px}
  /* The default focus ring is a hard black outline that reads as a mis-drawn
     border on a card. Use the brand accent, offset clear of the corner. */
  .pcat:focus-visible,.pcatr:focus-visible,.pcatm:focus-visible{outline:2px solid var(--accent);outline-offset:3px}
  /* ═══ LAYOUT ARCHETYPES — genuinely different structures (not just colour) ═══
     Applied as a body class (pl-<layout>) from the design. 'centered' = default. */
  /* Spotlight — big marketing landing: tall band, XL search, oversized heading, wide category grid. */
  body.pl-spotlight #px-content:not(:empty){padding:22px 0 58px}
  body.pl-spotlight .pcats{max-width:1000px;margin-top:34px}
  body.pl-spotlight .pcats-grid{grid-template-columns:repeat(auto-fit,minmax(172px,252px));gap:16px}
  body.pl-spotlight .wrap{max-width:720px}
  /* Editorial — left-aligned wide column, asymmetric magazine feel. */
  body.pl-editorial #px-content:not(:empty){padding:10px 0 30px}
  body.pl-editorial .pcats-t{text-align:left}
  body.pl-editorial .pcats{max-width:900px}
  body.pl-editorial .pcats-grid{justify-content:start;grid-template-columns:repeat(auto-fit,minmax(158px,232px))}
  body.pl-editorial .wrap{max-width:760px;margin-left:max(20px,calc((100% - 900px)/2 + 20px))}
  /* Cards — the category grid is the hero: big tiles, minimal heading, no subheading. */
  body.pl-cards #px-content:not(:empty){padding-bottom:42px}
  body.pl-cards .pcats{max-width:1000px;margin-top:22px}
  body.pl-cards .pcats-grid{grid-template-columns:repeat(auto-fill,minmax(200px,1fr));gap:16px}
  body.pl-cards .pcat{padding:32px 16px;gap:14px}
  body.pl-cards .pcat-ic{width:60px;height:60px;font-size:30px;border-radius:16px}
  body.pl-cards .pcat-l{font-size:15px}
  /* Compact — dense utility help-desk: no hero band, no hero, tight search + form. */
  body.pl-compact #px-content:not(:empty){background:none!important;padding:6px 0 0}
  body.pl-compact #px-content:not(:empty)::after{display:none}
  body.pl-compact .pcats{max-width:560px;margin-top:12px}
  body.pl-compact .pcats-grid{grid-template-columns:repeat(auto-fill,minmax(120px,1fr));gap:8px}
  body.pl-compact .pcat{padding:14px 10px;gap:7px}
  body.pl-compact .pcat-ic{width:40px;height:40px;font-size:20px}
  body.pl-compact .wrap{max-width:560px;padding-top:16px}
  body.pl-compact #px-content:not(:empty) + .wrap{padding-top:10px}

  /* ── PX_MATURITY v1 — component polish layer: depth system, typographic
     discipline, focus states, micro-interactions. Every studio design inherits
     this; tokens (--accent/--ink/--radius…) still drive all colour. ── */
  :root{--shadow-sm:0 1px 2px rgba(15,23,42,.05),0 1px 3px rgba(15,23,42,.06);
        --shadow-md:0 4px 6px -1px rgba(15,23,42,.05),0 10px 24px -6px rgba(15,23,42,.10);
        --shadow-lg:0 12px 20px -8px rgba(15,23,42,.13),0 28px 60px -12px rgba(15,23,42,.16);
        --ease:cubic-bezier(.22,.61,.36,1)}
  body{text-rendering:optimizeLegibility}
  .wrap{max-width:720px;padding:clamp(32px,3vw,56px) 20px 72px}
  .brandbar{margin-bottom:30px}
  .brandbar h1{font-size:20px;letter-spacing:-.02em}
  .card{border-color:color-mix(in srgb,var(--line) 74%,transparent);border-radius:calc(var(--radius) + 2px);padding:28px;box-shadow:var(--shadow-sm),var(--shadow-md)}
  .intro{font-size:14.5px;line-height:1.6}
  label{font-size:11.5px;text-transform:uppercase;letter-spacing:.07em;font-weight:800;margin:18px 0 7px}

  /* ── COMPOSE FORM RHYTHM ─────────────────────────────────────────────────
     Spacing is driven from the FIELDS, not from label top-margins. A pre-existing
     `label:first-child{margin-top:0}` was zeroing the gap above several labels,
     so the label sat hard against the field before it and the whole form read as
     one undifferentiated stack. Giving each control a bottom margin cannot be
     cancelled that way, and it keeps label-to-its-own-field tight (9px) while the
     gap BETWEEN field groups is clearly larger (24px). */
  #pg-new .card label{margin:0 0 9px}
  #pg-new .card input,#pg-new .card select,#pg-new .card textarea,
  #pg-new .card .prio-c,#pg-new .card .row,#pg-new .card .rte,#pg-new .card .px-ed,#pg-new .card .px-edwrap{margin-bottom:24px}
  /* the textarea's own margin is INSIDE .rte and escapes it, leaving the next
     label hard against the editor — the wrapper carries the gap instead */
  #pg-new .card .rte textarea{margin-bottom:0}
  /* the pair is one group: its inner fields must not double the gap */
  #pg-new .card .row input,#pg-new .card .row select,#pg-new .card .row .prio-c{margin-bottom:0}
  #pg-new .row{gap:18px}
  #pg-new .row > div{flex:1 1 240px;min-width:0}

  /* ── SUBMIT / CANCEL ─────────────────────────────────────────────────────
     Full width stays the default. 'small'/'large' size the button to its label
     and sit Cancel beside it as a quiet secondary. */
  /* Submit and Cancel are one pair: same height, same padding, same radius,
     sitting together at the start of the row. Cancel differs only in WEIGHT
     (outlined, not filled) — a secondary action, not a smaller one. Both had to
     be pinned to width:auto because the base .btn rule stretches to full width,
     which was blowing Cancel out to 671px. */
  .p-actions{display:flex;align-items:center;justify-content:flex-start;gap:12px;margin-top:8px}
  .p-actions.al-right{justify-content:flex-end}
  .p-actions.al-center{justify-content:center}
  /* alignment is meaningless when the button fills the row */
  .p-actions.sz-normal{justify-content:flex-start}
  .p-actions > .btn,.p-actions > #p-cancel{flex:0 0 auto;width:auto;margin-top:0;
    min-height:46px;padding:12px 26px;font-size:14px;font-weight:750;
    border-radius:var(--r-md,12px);cursor:pointer;transition:.15s var(--ease)}
  .p-actions.sz-small > .btn,.p-actions.sz-small > #p-cancel{min-height:42px;padding:11px 22px;font-size:13.5px}
  .p-actions.sz-large > .btn,.p-actions.sz-large > #p-cancel{min-height:54px;padding:16px 30px;font-size:16px}
  /* full width is still the default look when the operator wants it loud */
  .p-actions.sz-normal > .btn{flex:1 1 auto}
  .p-actions.sz-normal > #p-cancel{flex:0 0 auto}
  #p-cancel{background:transparent;border:1.5px solid var(--line);color:var(--ink-2);font-family:inherit}
  #p-cancel:hover{border-color:color-mix(in srgb,var(--ink) 26%,transparent);color:var(--ink);
    background:color-mix(in srgb,var(--ink) 4%,transparent)}
  #p-cancel.hidden{display:none}

  /* Busy: the whole form stops accepting input while the request is in flight,
     so what the customer sees cannot drift from what was sent. */
  #pg-new .card.is-busy{position:relative;pointer-events:none}
  #pg-new .card.is-busy input,#pg-new .card.is-busy select,
  #pg-new .card.is-busy textarea,#pg-new .card.is-busy .rte{opacity:.55}
  #pg-new .card.is-busy #p-submit{opacity:1;position:relative}
  #pg-new .card.is-busy #p-cancel{opacity:.4}
  /* The pair only becomes a row when the option is on AND both fields are
     actually visible — a lone survivor keeps the full width instead of sitting
     in a half-width column with dead space beside it. */
  #p-dept-prio-row.px-pair:has(> #p-dept-wrap:not(.hidden)):has(> #p-prio-wrap:not(.hidden)){
    display:flex;gap:18px;flex-wrap:wrap}
  #p-dept-prio-row.px-pair:has(> #p-dept-wrap:not(.hidden)):has(> #p-prio-wrap:not(.hidden)) > div{flex:1 1 240px;min-width:0}
  #pg-new textarea{margin-bottom:4px}
  input,select,textarea{padding:12px 14px;border-radius:12px;font-size:14.5px;transition:border-color .16s var(--ease),box-shadow .16s var(--ease)}
  input:hover:not(:focus),select:hover:not(:focus),textarea:hover:not(:focus){border-color:color-mix(in srgb,var(--ink-3) 50%,var(--line))}
  input:focus,select:focus,textarea:focus{border-color:var(--accent);box-shadow:0 0 0 4px color-mix(in srgb,var(--accent) 13%,transparent)}
  .btn{margin-top:22px;padding:14px 18px;border-radius:13px;letter-spacing:.004em;box-shadow:0 1px 2px rgba(15,23,42,.08),0 10px 22px -6px color-mix(in srgb,var(--accent) 42%,transparent);transition:transform .16s var(--ease),box-shadow .16s var(--ease),filter .16s var(--ease)}
  .btn:hover{transform:translateY(-1px);box-shadow:0 2px 4px rgba(15,23,42,.08),0 16px 32px -8px color-mix(in srgb,var(--accent) 52%,transparent)}
  .btn:active{transform:translateY(0) scale(.995)}
  .btn:focus-visible,.btn-ghost:focus-visible,.tabs button:focus-visible,.reqfilters button:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
  .tabs{padding:4px;border-radius:13px;background:color-mix(in srgb,var(--line-soft) 82%,transparent);border:1px solid color-mix(in srgb,var(--line) 55%,transparent)}
  .tabs button{padding:10px 12px;border-radius:10px}
  .tabs button.on{box-shadow:var(--shadow-sm)}
  .pill{padding:4.5px 12px;letter-spacing:.01em}
  .req{padding:16px 18px;border-radius:14px;transition:transform .18s var(--ease),box-shadow .18s var(--ease),border-color .18s var(--ease)}
  .req:hover{transform:translateY(-2px);box-shadow:var(--shadow-md);border-color:color-mix(in srgb,var(--accent) 32%,var(--line))}
  .req .rq-sub{font-size:14.5px}
  .reqfilters{gap:8px;margin-bottom:16px}
  .reqfilters button{padding:7px 14px;transition:.16s var(--ease)}
  .reqfilters button:hover{border-color:var(--accent);color:var(--accent)}
  .reqfilters button.on{box-shadow:0 6px 14px -4px color-mix(in srgb,var(--accent) 45%,transparent)}
  .btn-ghost{padding:13px;transition:.16s var(--ease)}
  .btn-ghost:hover{background:color-mix(in srgb,var(--accent) 5%,#fff);box-shadow:var(--shadow-sm)}
  .bubble{border-radius:14px;padding:13px 16px;box-shadow:var(--shadow-sm)}
  .bubble.support{background:color-mix(in srgb,var(--accent) 4%,#fff);border-color:color-mix(in srgb,var(--accent) 16%,var(--line))}
  .ticketno{border:1px dashed color-mix(in srgb,var(--ink-3) 42%,var(--line));background:color-mix(in srgb,var(--line-soft) 70%,#fff)}
  .deflect{border-radius:14px;background:color-mix(in srgb,var(--accent) 4%,var(--line-soft));border-color:color-mix(in srgb,var(--accent) 15%,var(--line))}
  .empty{padding:36px 6px}
  .acctbar{padding:10px 14px;border:1px solid var(--line-soft);border-radius:12px;background:color-mix(in srgb,var(--card) 55%,var(--line-soft))}
  .phero-h{letter-spacing:-.032em}
  .phero-s{font-size:16px;line-height:1.6}
  .psearch-in{padding:16px 19px;border-radius:17px}
  .psearch-in:focus-within{border-color:var(--accent);box-shadow:0 0 0 4px color-mix(in srgb,var(--accent) 12%,transparent),0 18px 46px -10px color-mix(in srgb,var(--accent) 34%,transparent)}
  .pcat{border-radius:15px;transition:transform .18s var(--ease),box-shadow .18s var(--ease),border-color .18s var(--ease)}
  .pcat:hover{transform:translateY(-3px);box-shadow:var(--shadow-md);border-color:color-mix(in srgb,var(--accent) 30%,var(--line))}
  .pcat-ic{width:44px;height:44px;display:flex;align-items:center;justify-content:center;font-size:22px;border-radius:13px;background:color-mix(in srgb,var(--accent) 9%,var(--line-soft))}
  .pcat-l{font-weight:750;font-size:14px;letter-spacing:-.005em}
  .pnav-in{min-height:62px}
  .pnav{backdrop-filter:blur(14px) saturate(1.4);-webkit-backdrop-filter:blur(14px) saturate(1.4);border-bottom-color:color-mix(in srgb,var(--line) 70%,transparent)}
  .pfoot-col a{padding:5px 0;transition:color .14s var(--ease)}
  /* MAT2 — category layout variants + svg icon colouring + tile descriptions */
  .pcat-ic svg,.pcatm-ic svg,.pb-card-ic svg,.pb-ct-ic svg{display:block;color:var(--accent)}
  .pcat-d{font-size:12.5px;color:var(--ink-3);line-height:1.45;text-align:center;margin-top:-4px}
  .pcats-rows{display:grid;grid-template-columns:repeat(auto-fill,minmax(300px,1fr));gap:12px;max-width:var(--px-cw,780px);margin:0 auto;padding:0 20px}
  .pcatr{display:flex;align-items:center;gap:14px;background:var(--card);border:1px solid var(--line);border-radius:15px;padding:16px 18px;text-decoration:none;box-shadow:0 1px 2px rgba(15,23,42,.04);transition:transform .18s var(--ease),box-shadow .18s var(--ease),border-color .18s var(--ease)}
  .pcatr:hover{transform:translateY(-2px);box-shadow:var(--shadow-md);border-color:color-mix(in srgb,var(--accent) 30%,var(--line))}
  .pcatr .pcat-ic{flex-shrink:0}
  .pcatr-tx{flex:1;min-width:0;display:flex;flex-direction:column;gap:2px}
  .pcatr-l{font-weight:750;font-size:14.5px;color:var(--ink);letter-spacing:-.005em}
  .pcatr-d{font-size:12.5px;color:var(--ink-3);line-height:1.45;overflow:hidden;text-overflow:ellipsis;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical}
  .pcatr-arr{flex-shrink:0;color:var(--ink-3);transition:transform .18s var(--ease),color .18s var(--ease)}
  .pcatr:hover .pcatr-arr{transform:translateX(3px);color:var(--accent)}
  .pcats-min{display:grid;grid-template-columns:repeat(auto-fill,minmax(220px,1fr));gap:4px;max-width:var(--px-cw,780px);margin:0 auto;padding:0 20px}
  .pcatm{display:flex;align-items:center;gap:10px;padding:11px 12px;border-radius:11px;text-decoration:none;font-weight:650;font-size:14px;color:var(--ink);transition:background .15s var(--ease),color .15s var(--ease)}
  .pcatm:hover{background:color-mix(in srgb,var(--accent) 7%,transparent);color:var(--accent)}
  .pcatm .pcatr-arr{margin-left:auto;opacity:0;transition:.15s var(--ease)}
  .pcatm:hover .pcatr-arr{opacity:1;transform:translateX(2px)}
  .pcatm-ic{display:flex;color:var(--accent)}
  /* SP3 — chat-style conversation */
  .thread{gap:14px}
  /* P14 — the avatar sits at the TOP of the bubble, beside the author name it
     belongs to. Bottom-aligned, a three-line message left the "J" circle ~100px
     below "JORDAN", reading as an orphan. Seven of the ten bubble styles already
     overrode this to flex-start, so the base was the odd one out. */
  .brow{display:flex;gap:10px;align-items:flex-start}
  .brow.mine{flex-direction:row-reverse}
  /* thread message entrance (embed parity) — gated on the motion setting, staggered */
  @keyframes pxMsgIn{from{opacity:0;transform:translateY(8px)}to{opacity:1;transform:none}}
  body[class*="tkm-"]:not(.tkm-none) .thread .brow{animation:pxMsgIn .42s var(--ease) both}
  body[class*="tkm-"] .thread .brow:nth-child(2){animation-delay:.05s}
  body[class*="tkm-"] .thread .brow:nth-child(3){animation-delay:.1s}
  body[class*="tkm-"] .thread .brow:nth-child(4){animation-delay:.15s}
  body[class*="tkm-"] .thread .brow:nth-child(n+5){animation-delay:.18s}
  @media(prefers-reduced-motion:reduce){.thread .brow{animation:none!important}}
  /* ⚠ A REBUILD IS NOT AN ENTRANCE. `pxRenderThread` empties the thread and recreates every row, so
     after a reply the entrance animation replayed on all of them at once and read as the whole page
     blinking. `t-noanim` is set by the renderer while it is REBUILDING an already-open thread; a
     genuine open still animates. */
  .thread.t-noanim .brow{animation:none!important}
  .brow .bubble{max-width:calc(100% - 60px);flex:0 1 auto}
  /* ══ P14 · WHO IS SPEAKING MUST BE UNMISTAKABLE ═══════════════════════════
     A 7% accent tint on the customer bubble against an untinted agent bubble
     made the two read as the same message. For a corporate portal the two
     voices are given different WEIGHT, not just different colour:

       agent  = the organisation speaking. A solid card on the surface colour
                with a brand rail down its leading edge and real elevation —
                the authoritative record.
       you    = clearly the customer's own words. A meaningfully tinted panel,
                flatter, no rail, tail on the reply side.

     The styles that deliberately flatten the thread (flat-thread, minimal-lines,
     timeline-dots, email-style, ticket-classic) all override with !important, so
     they are unaffected. ══════════════════════════════════════════════════ */
  .thread .brow:not(.mine) .bubble{
    background:var(--card);
    border-color:var(--line);
    /* ⚠ --accent-bg may hold a GRADIENT, which is invalid as a <color>. Used in a
       border shorthand it makes the declaration invalid at computed-value time,
       so border-left-style falls back to `none` and the width computes to 0px —
       the rail silently vanished. Border colours must use --accent. */
    border-left:3px solid var(--accent);
    box-shadow:0 1px 2px rgba(15,23,42,.05),0 10px 24px -16px rgba(15,23,42,.3);
  }
  .thread .brow:not(.mine) .who{color:var(--accent);letter-spacing:.5px}
  .thread .brow:not(.mine) .avat{box-shadow:0 0 0 2px var(--card),0 0 0 3.5px color-mix(in srgb,var(--accent) 45%,transparent)}
  .bubble.mine{
    background:color-mix(in srgb,var(--accent) 13%,var(--card));
    border-color:color-mix(in srgb,var(--accent) 26%,var(--line));
    border-bottom-right-radius:6px;
    box-shadow:none;
  }
  .thread .brow.mine .who{color:color-mix(in srgb,var(--ink) 62%,transparent)}
  .brow:not(.mine) .bubble{border-bottom-left-radius:6px}
  .avat{flex-shrink:0;width:32px;height:32px;border-radius:50%;display:flex;align-items:center;justify-content:center;font-size:12px;font-weight:800;color:#fff;background:var(--accent-bg,var(--accent));box-shadow:var(--shadow-sm)}
  .avat.cust{background:linear-gradient(135deg,#64748b,#94a3b8)}
  /* P14 — the day separator was bare grey text between two hairlines, which on
     a long thread read as an accident rather than a marker. It is now a pill
     seated ON the rule: legible at a glance while scanning, and it survives a
     tinted or dark surface because it carries its own background. */
  .tsep{display:flex;align-items:center;gap:14px;margin:22px 0 14px;
    color:var(--ink-3);font-size:11px;font-weight:800;letter-spacing:.1em;text-transform:uppercase}
  .tsep::before,.tsep::after{content:"";flex:1;height:1px;
    background:linear-gradient(90deg,transparent,var(--line),transparent)}
  .tsep{position:relative}
  .tsep>span,.tsep{white-space:nowrap}
  .thread .tsep{padding:0}
  /* the label itself sits in a chip */
  .tsep-chip{background:var(--card);border:1px solid var(--line-soft,var(--line));border-radius:999px;
    padding:5px 13px;box-shadow:0 1px 2px rgba(15,23,42,.04);color:var(--ink-2)}
  .bubble .body a{color:var(--accent);font-weight:600}.bubble .body code{background:var(--line-soft);border-radius:5px;padding:1px 5px;font-size:.92em}
  /* ═══ W4 — 10 bubble styles (bs-*) ═══ */
  .bs-chat-square .bubble{border-radius:8px}
  .bs-cards .brow{align-items:flex-start}.bs-cards .bubble{border-radius:14px;box-shadow:var(--shadow-md)}.bs-cards .bubble.mine{background:var(--card)}
  .bs-flat-thread .brow{align-items:flex-start}.bs-flat-thread .brow.mine{flex-direction:row}.bs-flat-thread .bubble{background:transparent!important;border:none!important;box-shadow:none!important;border-bottom:1px solid var(--line-soft)!important;border-radius:0;padding:12px 0;max-width:100%!important}.bs-flat-thread .brow .bubble{max-width:100%}
  .bs-boxed-quote .bubble{border-left:3px solid var(--line);border-radius:0 10px 10px 0;box-shadow:none}.bs-boxed-quote .bubble.support{border-left-color:var(--accent)}
  .bs-timeline-dots .brow{align-items:flex-start}.bs-timeline-dots .brow.mine{flex-direction:row}.bs-timeline-dots .avat{width:12px;height:12px;font-size:0;background:var(--ink-3)}.bs-timeline-dots .avat.cust,.bs-timeline-dots .brow:not(.mine) .avat{background:var(--accent)}.bs-timeline-dots .bubble{background:transparent!important;border:none!important;box-shadow:none!important;padding:2px 0 14px;max-width:100%!important}
  .bs-minimal-lines .brow{align-items:flex-start}.bs-minimal-lines .brow.mine{flex-direction:row}.bs-minimal-lines .avat{display:none}.bs-minimal-lines .bubble{background:transparent!important;border:none!important;box-shadow:none!important;border-radius:0;padding:8px 0;max-width:100%!important}.bs-minimal-lines .who{color:var(--accent)}
  .bs-email-style .brow{align-items:flex-start}.bs-email-style .brow.mine{flex-direction:row}.bs-email-style .bubble{background:#fff!important;border:1px solid var(--line)!important;border-radius:10px;max-width:100%!important;box-shadow:var(--shadow-sm)}.bs-email-style .who{border-bottom:1px solid var(--line-soft);padding-bottom:6px;margin-bottom:6px;text-transform:none;font-size:13px;color:var(--ink)}
  .bs-ticket-classic .brow{align-items:flex-start;flex-direction:row!important}.bs-ticket-classic .bubble{background:#fff!important;border:1px solid var(--line)!important;border-radius:8px;max-width:100%!important}.bs-ticket-classic .brow.mine .bubble{background:color-mix(in srgb,var(--accent) 5%,#fff)!important}.bs-ticket-classic .who{background:var(--line-soft);margin:-13px -16px 10px;padding:8px 16px;border-radius:8px 8px 0 0;text-transform:none;font-size:12.5px;color:var(--ink)}
  /* ══ THE FLAT FAMILY STILL HAS TO NAME ITS SPEAKER ════════════════════════
     flat-thread, timeline-dots, minimal-lines and email-style all render the
     agent and the customer IDENTICALLY — measured signature-for-signature — so
     the only cue was the author label. These styles flatten on purpose, so the
     voice is carried by a brand rail on the ORGANISATION's messages and a
     muted label on the customer's: their flat identity survives, the speaker
     becomes unmistakable. They override with !important, so this must too. ══ */
  .bs-flat-thread .brow:not(.mine) .bubble,
  .bs-minimal-lines .brow:not(.mine) .bubble,
  .bs-email-style .brow:not(.mine) .bubble{
    border-left:3px solid var(--accent)!important;
    padding-left:15px!important;
  }
  .bs-flat-thread .brow:not(.mine) .who,
  .bs-minimal-lines .brow:not(.mine) .who,
  .bs-email-style .brow:not(.mine) .who,
  .bs-timeline-dots .brow:not(.mine) .who{color:var(--accent)}
  .bs-flat-thread .brow.mine .who,
  .bs-minimal-lines .brow.mine .who,
  .bs-email-style .brow.mine .who,
  .bs-timeline-dots .brow.mine .who{color:color-mix(in srgb,var(--ink) 55%,transparent)}
  /* timeline-dots keeps its rail-less timeline: the agent's DOT carries the
     accent (already) and the customer's is muted, so the two never match. */
  .bs-timeline-dots .brow.mine .avat{background:var(--ink-3)!important;opacity:.6}
  .bs-glass .bubble{backdrop-filter:blur(12px) saturate(1.4);background:color-mix(in srgb,var(--card) 65%,transparent)!important;border-color:color-mix(in srgb,#fff 40%,var(--line))!important;box-shadow:var(--shadow-lg)}
  /* ADDITIVE_PORTAL_PREMIUM_2026 — two new conversation treatments. */
  .bs-case-cards .brow{align-items:flex-start}.bs-case-cards .bubble{max-width:min(760px,88%);border-radius:16px;border:1px solid color-mix(in srgb,var(--accent) 13%,var(--line));box-shadow:0 14px 35px -28px rgba(15,23,42,.5);padding:16px 18px;background:linear-gradient(145deg,color-mix(in srgb,var(--card) 96%,var(--accent) 4%),var(--card))}.bs-case-cards .brow:not(.mine) .bubble{border-left:4px solid var(--accent)}.bs-case-cards .brow.mine .bubble{border-right:4px solid color-mix(in srgb,var(--ink-3) 60%,transparent);background:color-mix(in srgb,var(--accent) 5%,var(--card))}.bs-case-cards .who{font-size:12.5px;text-transform:none;letter-spacing:0;color:var(--ink);padding-bottom:7px;margin-bottom:8px;border-bottom:1px solid var(--line-soft)}
  .bs-support-notes .brow{align-items:flex-start;flex-direction:row!important}.bs-support-notes .avat{border-radius:10px}.bs-support-notes .bubble{max-width:100%!important;border-radius:0 13px 13px 0;border:0;border-left:4px solid var(--accent);box-shadow:none;background:color-mix(in srgb,var(--accent) 4%,var(--card))!important;padding:14px 17px}.bs-support-notes .brow.mine .bubble{border-left-color:var(--ink-3);background:color-mix(in srgb,var(--ink) 2%,var(--card))!important}.bs-support-notes .who{font-size:12px;text-transform:uppercase;letter-spacing:.05em;color:var(--accent)}.bs-support-notes .brow.mine .who{color:var(--ink-3)}
  .thread.side-names .avat{display:none}.thread.side-names .who{font-size:12.5px}
  /* W5 — bubble alignment (positionable) */
  .ba-customer-left .brow.mine{flex-direction:row}.ba-customer-left .bubble.mine{border-bottom-right-radius:14px;border-bottom-left-radius:6px}
  .ba-all-left .brow.mine{flex-direction:row}.ba-all-left .brow{align-items:flex-start}
  /* W5 — reply rating widget */
  .rr{display:flex;align-items:center;gap:10px;flex-wrap:wrap;margin-top:12px;padding-top:10px;border-top:1px dashed var(--line)}
  .rr.ra-center{justify-content:center}.rr.ra-right{justify-content:flex-end}
  /* reply reactions — quick "like" (separate from rating) */
  .rx{display:flex;align-items:center;gap:6px;margin-top:8px;flex-wrap:wrap}
  .rx-b{border:1px solid var(--line);background:var(--card);border-radius:999px;padding:5px 11px;font-size:14px;line-height:1;cursor:pointer;transition:.14s var(--ease);display:inline-flex;align-items:center;gap:5px;color:var(--ink-2)}
  .rx-b .rx-t{font-size:12.5px;font-weight:700}
  .rx-b:hover{border-color:var(--accent);transform:translateY(-1px)}
  .rx-b.on{border-color:var(--accent);background:color-mix(in srgb,var(--accent) 12%,transparent);color:var(--accent)}
  /* "Your turn" turn badge (embed parity) + awaiting-row highlight */
  .px-turn{display:inline-block;padding:4px 11px;border-radius:999px;font-size:11px;font-weight:900;letter-spacing:.03em;text-transform:uppercase;color:#fff;background:var(--accent-bg,linear-gradient(135deg,var(--accent),var(--accent-d)));box-shadow:0 4px 12px -3px color-mix(in srgb,var(--accent) 55%,transparent);white-space:nowrap;margin-right:2px;vertical-align:middle}
  #px-d-subject .px-turn{font-size:12px;margin-left:10px}
  .awaiting{position:relative;background:linear-gradient(135deg,color-mix(in srgb,var(--accent) 7%,var(--card)),var(--card))!important;border-color:color-mix(in srgb,var(--accent) 30%,var(--line))!important}
  .px-tcard.awaiting,.px-cozy-row.awaiting,.tl-item.awaiting,.kb-card.awaiting,.sp-row.awaiting,.px-line.awaiting,.psd-row.awaiting,.pac-card.awaiting{border-left:3px solid var(--accent)}
  /* PHASE_PORTAL_TKLIST — row accent by status/priority (mirrors the .awaiting border pattern) */
  .pxra:not(tr){border-left:3px solid var(--row-accent)}
  tr.pxra>td:first-child{border-left:3px solid var(--row-accent)}
  tr.awaiting{background:linear-gradient(135deg,color-mix(in srgb,var(--accent) 6%,transparent),transparent)}
  tr.awaiting .rt-subcell{box-shadow:inset 3px 0 0 var(--accent)}
  .rr-label{font-size:11.5px;font-weight:800;text-transform:uppercase;letter-spacing:.05em;color:var(--ink-3)}
  .rr[data-done] .rr-label{color:var(--ok)}
  .rr-ctl{display:inline-flex;gap:4px;align-items:center}
  .rr-b{background:none;border:none;font-size:17px;cursor:pointer;opacity:.5;transition:.13s var(--ease);padding:2px 4px;border-radius:7px}
  .rr-b:hover{opacity:1;transform:scale(1.12)}.rr-b.on{opacity:1}
  .rr-stars{display:inline-flex}
  .rr-star{background:none;border:none;font-size:18px;line-height:1;cursor:pointer;color:var(--line);transition:color .12s var(--ease),transform .12s var(--ease);padding:1px}
  .rr-star:hover{transform:scale(1.15)}.rr-star.on{color:#f59e0b}
  .rr[data-done] .rr-b,.rr[data-done] .rr-star{pointer-events:none}
  .rr-comment{flex-basis:100%;margin-top:8px;display:flex;gap:8px;flex-direction:column}
  .rr-comment textarea{min-height:52px}.rr-send{margin:0;align-self:flex-start;width:auto;padding:8px 16px}
  /* avatar styles */
  .av-initials-squircle{border-radius:9px}
  .av-initials-gradient{background:linear-gradient(135deg,var(--accent),#8b5cf6)!important}
  .av-monogram-outline{background:transparent!important;color:var(--accent)!important;border:2px solid var(--accent);box-shadow:none}
  .av-dot-status{background:var(--line-soft)!important;position:relative}.av-statusdot{width:11px;height:11px;border-radius:50%;background:var(--ink-3)}.av-statusdot.answered,.av-statusdot.closed,.av-statusdot.resolved{background:var(--ok)}.av-statusdot.open,.av-statusdot.customer_reply{background:var(--accent)}
  .av-emoji{background:var(--line-soft)!important;font-size:16px}
  /* ═══ W4 — status stepper (6 styles) ═══ */
  .stepper{display:flex;align-items:center;gap:0;margin:0 0 16px;flex-wrap:wrap}
  .step{display:flex;align-items:center;gap:7px;flex-shrink:0}
  .step-mark{width:24px;height:24px;border-radius:50%;background:var(--line-soft);color:var(--ink-3);font-size:12px;font-weight:800;display:flex;align-items:center;justify-content:center;border:1px solid var(--line)}
  .step.done .step-mark{background:var(--ok);color:#fff;border-color:var(--ok)}.step.now .step-mark{background:var(--accent);color:#fff;border-color:var(--accent)}
  .step-lbl{font-size:12px;font-weight:700;color:var(--ink-3)}.step.now .step-lbl,.step.done .step-lbl{color:var(--ink)}
  .step-line{flex:1;min-width:16px;height:2px;background:var(--line);margin:0 8px}.step-line.done{background:var(--ok)}
  .st-dots .step-mark{width:12px;height:12px;font-size:0}.st-dots .step-lbl{display:none}
  .st-bar{gap:0}.st-bar .step{flex:1;flex-direction:column;gap:5px}.st-bar .step-mark{display:none}.st-bar .step-lbl{font-size:11px}.st-bar .step-line{display:none}.st-bar .step{border-top:3px solid var(--line);padding-top:7px}.st-bar .step.done{border-color:var(--ok)}.st-bar .step.now{border-color:var(--accent)}
  /* P14 — the pills row carried full done/now/upcoming semantics in the DOM
     (.step.done + ✓, .step.now, .step-line.done) but suppressed the mark AND the
     connectors, so a completed step differed from an upcoming one only by a
     faint tint and the row never read as a PROGRESSION. The tick is restored for
     completed steps and upcoming steps are visibly muted. */
  .st-pills-row .step-mark{display:none}
  .st-pills-row .step.done .step-lbl::before{content:'✓';margin-right:6px;font-weight:900;color:var(--ok,#16a34a)}
  .st-pills-row .step:not(.done):not(.now){opacity:.55}
  .st-pills-row .step:not(.done):not(.now) .step-lbl{color:var(--ink-3)}
  .st-pills-row .step-line{display:none}.st-pills-row .step{background:var(--line-soft);border-radius:999px;padding:5px 13px;margin-right:6px}.st-pills-row .step.now{background:var(--accent)}.st-pills-row .step.now .step-lbl{color:#fff}.st-pills-row .step.done{background:color-mix(in srgb,var(--ok) 15%,transparent)}
  .st-vertical{flex-direction:column;align-items:flex-start}.st-vertical .step{margin-bottom:8px}.st-vertical .step-line{display:none}
  .st-checklist{flex-direction:column;align-items:flex-start}.st-checklist .step-line{display:none}.st-checklist .step{margin-bottom:6px}.st-checklist .step-mark{border-radius:6px}
  /* ═══ W4 — detail layouts (dl-*) ═══ */
  /* ⚠ ADDING A VARIANT HERE? The mobile collapse at ~L2048 uses `.rq-grid.rq-grid` to
     outrank this whole family — leave it doubled or your variant will keep its desktop
     columns on a phone (that is exactly how dl-wide came to render the thread at 0px).
     ⚠ EVERY ONE OF THESE MUST BE SCOPED `.rq-grid.dl-*`, NOT BARE `.dl-*`.
     The base `.rq-grid{grid-template-columns:minmax(0,1fr) 280px}` is declared
     LATER in this stylesheet at equal (0,1,0) specificity, so a bare `.dl-*`
     rule always lost and every layout computed the same 613px/280px. Only the
     rules using other properties (order, display) appeared to work — which is
     why `sidebar-left` swapped the ORDER but kept the widths, handing the
     sidebar 613px and squeezing the conversation into 280px. */
  .rq-grid.dl-sidebar-left{grid-template-columns:280px minmax(0,1fr)}.dl-sidebar-left .rq-side{order:-1}

/* ═══ LAYOUT 2 — THE CORRESPONDENCE LEDGER ═══════════════════════════════════════════════════
   Layout 2 used to be a duplicate: its only rule was "put the sidebar left", which the separate
   `Sidebar side` setting already does — with one id + one class, so it WON. All four combinations
   were measured: the layout changed nothing, and picking "Sidebar left" with the side set to right
   rendered on the RIGHT. It was a name with nothing behind it.

   It earns its place by changing the READING COLUMN. The other layouts render a chat: round
   bubbles, tails, soft fills. This renders CORRESPONDENCE — the register a large organisation uses
   for a case file. Direction still reads at a glance, because that is genuinely useful: what the
   client sent enters from the LEFT, what the desk sent leaves from the RIGHT. What changes is the
   finish. Each entry is a bordered document panel with a squared corner, a solid edge rule on its
   outer side, the author set in letterspaced caps beside its identity plate, and the absolute
   timestamp opposite in tabular figures. No tails, no pill shapes, no centred text.

   ⚠ SCOPED ENTIRELY TO `#px-d-grid.dl-sidebar-left`. One id + one class beats every existing thread
   rule (the strongest is three classes), and the class exists on no other layout, so none of the
   other eight can be reached by anything below.

   ⚠ COLOUR IS APPLIED EXACTLY AS EVERYWHERE ELSE — every value is mixed from --accent / --ink /
   --card / --line, so the operator's theme drives this layout like the others. No literals; asserted.

   ⚠ `.mine` IS THE CLIENT, NOT THE DESK. The renderer sets `'brow'+(isSup?'':' mine')`, so `.mine`
   is the customer and `:not(.mine)` is support. Reading it the other way inverts the whole layout.

   ⚠ NO CSS-GENERATED TEXT. A role badge via `content:` cannot be translated and would be English on
   all 40 locales. Direction is carried by side, edge rule and surface instead.

   ⚠ `bubble_style` and `bubble_align` DO NOT APPLY HERE, by design — this layout is defined by not
   being a chat, so a bubble shape and an alignment have nothing to act on. Every other thread
   setting still works: order, grouping, day separators, avatar style, agent HTML, collapse. */

#px-d-grid.dl-sidebar-left .thread{display:block;gap:0}

/* ── THE ENTRY ── held to a measure so the direction reads; never the full column. */
/* ⚠ FULL WIDTH, BOTH SIDES. An earlier pass held each entry to 82% and pushed it left or right,
   which is the chat gesture in a squarer costume and wastes a fifth of the column on every row.
   Every entry now spans the FULL measure; the direction is carried by which edge the identity plate
   sits on, which edge the solid rule runs down, and which end the author line is set to. */
/* ⚠ A GUTTER ON BOTH SIDES OF EVERY ROW, ALWAYS. Giving the plate a column only on its own side
   made the two panels the same WIDTH but not the same RECTANGLE: each was shunted 53px towards the
   plate, so client and desk entries never lined up down the column. Both gutters are now reserved
   on every row and the panel always occupies the middle column, so the sheet is identical whichever
   direction it travelled — only the gutter that is FILLED changes. */
#px-d-grid.dl-sidebar-left .thread .brow,
#px-d-grid.dl-sidebar-left .thread .brow.mine,
#px-d-grid.dl-sidebar-left .thread .brow:not(.mine){
  display:grid;grid-template-columns:40px minmax(0,1fr) 40px;column-gap:13px;
  align-items:start;
  max-width:100%;width:100%;margin:0 0 14px;padding:0;border:0;
  flex-direction:row;
}
#px-d-grid.dl-sidebar-left .thread .brow .bubble{grid-column:2;grid-row:1}
/* THE CLIENT enters from the left, so its plate fills the LEFT gutter. `.mine` is the customer. */
#px-d-grid.dl-sidebar-left .thread .brow.mine .avat{grid-column:1;grid-row:1}
/* THE DESK leaves from the right, so its plate fills the RIGHT gutter. */
#px-d-grid.dl-sidebar-left .thread .brow:not(.mine) .avat{grid-column:3;grid-row:1}
/* A run by one author tightens up rather than repeating the full gap. */
#px-d-grid.dl-sidebar-left .thread .brow.bgroup{margin-bottom:7px}

/* ── THE IDENTITY PLATE ── squared, not a chat circle. */
#px-d-grid.dl-sidebar-left .thread .avat{
  width:34px;height:34px;border-radius:7px;
  font-size:11.5px;font-weight:800;letter-spacing:.02em;box-shadow:none;
  background:var(--accent-bg,var(--accent));color:var(--card);
}
#px-d-grid.dl-sidebar-left .thread .avat.cust{
  background:color-mix(in srgb,var(--ink) 10%,var(--card));
  color:color-mix(in srgb,var(--ink) 72%,transparent);
  border:1px solid color-mix(in srgb,var(--ink) 14%,transparent);
}

/* ── THE DOCUMENT PANEL ── a bordered sheet with a squared corner and a solid edge rule on the side
   it came from. This is what replaces the bubble. */
#px-d-grid.dl-sidebar-left .thread .bubble{
  max-width:100%;width:100%;margin:0;
  border-radius:5px;box-shadow:none;
  padding:11px 15px 13px;
  display:grid;grid-template-columns:minmax(0,1fr) auto;column-gap:16px;row-gap:8px;
}
/* ⚠ ONE SHEET, TWO DIRECTIONS. The client used to get neutral stock and a grey rule while the desk
   got accent stock and an accent rule, which made the two read as different objects rather than as
   the same document travelling opposite ways. They now share the identical surface, border, weight
   and corner: the ONLY things that flip are which edge carries the solid rule and which end the
   author line is set to. */
#px-d-grid.dl-sidebar-left .thread .bubble{
  background:color-mix(in srgb,var(--accent) 5%,var(--card));
  border:1px solid color-mix(in srgb,var(--accent) 22%,var(--line));
}
/* ⚠ THE TWO EDGES MUST NOT BE THE SAME COLOUR. Both rules were the accent, so side was the only
   difference and a glance down the column told you nothing — the record has to say WHO at a glance,
   not just which way. The desk keeps the accent, because outbound is the brand speaking. The client
   takes graphite mixed from --ink, which is the same token family and so still follows the theme.
   The surface, border, corner and rectangle stay identical between the two; only the rule colour,
   the rule side and the name side differ. */
#px-d-grid.dl-sidebar-left .thread .bubble{
  transition:border-color .18s var(--ease,ease), box-shadow .18s var(--ease,ease),
             background .18s var(--ease,ease);
}
/* Client — graphite rule on the LEFT, the side it entered from. */
#px-d-grid.dl-sidebar-left .thread .brow.mine .bubble{
  border-left:3px solid color-mix(in srgb,var(--ink) 42%,transparent);
  border-right:1px solid color-mix(in srgb,var(--accent) 22%,var(--line));
}
/* Desk — accent rule on the RIGHT, the side it left from. */
#px-d-grid.dl-sidebar-left .thread .brow:not(.mine) .bubble{
  border-left:1px solid color-mix(in srgb,var(--accent) 22%,var(--line));
  border-right:3px solid var(--accent);
  border-bottom-left-radius:5px;
}

/* ── HOVER ── the sheet lifts off the page and its own rule deepens, so the entry under the cursor
   is unmistakable without moving anything. Each side answers in its own colour. */
#px-d-grid.dl-sidebar-left .thread .brow:hover .bubble{
  background:var(--card);
}
#px-d-grid.dl-sidebar-left .thread .brow.mine:hover .bubble{
  border-color:color-mix(in srgb,var(--ink) 22%,var(--line));
  border-left-color:color-mix(in srgb,var(--ink) 68%,transparent);
  box-shadow:
    0 1px 2px color-mix(in srgb,var(--ink) 6%,transparent),
    0 6px 16px -8px color-mix(in srgb,var(--ink) 34%,transparent);
}
#px-d-grid.dl-sidebar-left .thread .brow:not(.mine):hover .bubble{
  border-color:color-mix(in srgb,var(--accent) 40%,var(--line));
  border-right-color:var(--accent);
  box-shadow:
    0 1px 2px color-mix(in srgb,var(--ink) 6%,transparent),
    0 6px 16px -8px color-mix(in srgb,var(--accent) 46%,transparent);
}
/* The identity plate answers the hover too, so the row reads as one object. */
#px-d-grid.dl-sidebar-left .thread .avat{transition:box-shadow .18s var(--ease,ease)}
#px-d-grid.dl-sidebar-left .thread .brow:not(.mine):hover .avat{
  box-shadow:0 0 0 3px color-mix(in srgb,var(--accent) 20%,transparent);
}
#px-d-grid.dl-sidebar-left .thread .brow.mine:hover .avat{
  box-shadow:0 0 0 3px color-mix(in srgb,var(--ink) 12%,transparent);
}

/* ── THE HEADER LINE ── author beside its own plate, timestamp opposite, so the two sides mirror
   and each name stays next to the face it belongs to. */
#px-d-grid.dl-sidebar-left .thread .bubble > .who{
  grid-row:1;margin:0;
  font-size:11px;font-weight:800;letter-spacing:.1em;text-transform:uppercase;
}
#px-d-grid.dl-sidebar-left .thread .bubble > .at{
  grid-row:1;margin:0;
  font-size:10.5px;font-variant-numeric:tabular-nums;white-space:nowrap;
  color:color-mix(in srgb,var(--ink) 46%,transparent);
}
#px-d-grid.dl-sidebar-left .thread .brow.mine .bubble > .who{grid-column:1;text-align:left}
#px-d-grid.dl-sidebar-left .thread .brow.mine .bubble > .at{grid-column:2;text-align:right}
#px-d-grid.dl-sidebar-left .thread .brow:not(.mine) .bubble > .who{grid-column:2;text-align:right}
#px-d-grid.dl-sidebar-left .thread .brow:not(.mine) .bubble > .at{grid-column:1;text-align:left}
/* A hairline under the header separates the letterhead from the letter. */
#px-d-grid.dl-sidebar-left .thread .bubble > .body{
  grid-column:1 / -1;grid-row:2;
  padding-top:9px;
  border-top:1px solid color-mix(in srgb,var(--ink) 9%,transparent);
  font-size:13.5px;line-height:1.62;
  text-align:left;   /* prose is never right-aligned, whichever side the sheet sits on */
}
#px-d-grid.dl-sidebar-left .thread .bubble > *:not(.who):not(.at):not(.body){grid-column:1 / -1}
#px-d-grid.dl-sidebar-left .thread .bubble > .att{
  border:1px solid var(--line);border-radius:5px;padding:9px 11px;
  background:color-mix(in srgb,var(--card) 70%,transparent);
}

/* ── THE DAY SEPARATOR ── a ruled band across the full column, the way a file is dated. */
#px-d-grid.dl-sidebar-left .thread .tsep{
  display:block;margin:20px 0 14px;padding:0 0 7px;
  border-bottom:1px solid var(--line);
}
#px-d-grid.dl-sidebar-left .thread .tsep::before,
#px-d-grid.dl-sidebar-left .thread .tsep::after{content:none}
#px-d-grid.dl-sidebar-left .thread .tsep-chip{
  background:none;border:0;padding:0;border-radius:0;box-shadow:none;
  font-size:10px;font-weight:800;letter-spacing:.18em;text-transform:uppercase;
  color:color-mix(in srgb,var(--ink) 50%,transparent);
}

/* ── THE LETTERHEAD ── the header region belongs to the same register as the ledger below it, so
   the rounded, chat-era chrome is squared off: pill chips become tabs, the pill Reply becomes a
   squared action, and the utility strip becomes a ruled bar rather than floating controls.
   Two ids + one class here, so these beat the base `.d-*` rules without !important, and they still
   cannot escape this layout. */
/* ⚠ SET padding-bottom ONLY, NEVER THE PADDING SHORTHAND. In sticky-header mode the card pulls this
   block out with `margin:-4px -20px` and pays it back with `padding:10px 20px`. A shorthand here
   wiped that horizontal padding while the negative margin stayed, so the subject and the fact tabs
   hung 20px further left than the utility bar and the entries below them (measured: 380 against
   400). Only the bottom edge is ours to set. */
#px-d-grid.dl-sidebar-left #px-d-head{
  padding-bottom:13px;margin-bottom:0;
  border-bottom:2px solid color-mix(in srgb,var(--ink) 14%,transparent);
}
#px-d-grid.dl-sidebar-left #px-d-subject{letter-spacing:-.015em}
/* Reply — squared to match the document panels, not a pill floating over them. */
#px-d-grid.dl-sidebar-left #px-d-reply-top{
  border-radius:5px;box-shadow:none;
}
/* The facts read as filing tabs: squared, hairlined, tabular where they are numbers. */
#px-d-grid.dl-sidebar-left #px-d-head .d-chip{
  border-radius:4px;padding:4px 10px;
  font-variant-numeric:tabular-nums;
  background:color-mix(in srgb,var(--ink) 3.5%,transparent);
}
#px-d-grid.dl-sidebar-left #px-d-head #px-live-presence{
  border-radius:4px;
}
/* THE UTILITY BAR — one ruled strip carrying the count, the actions and the search, instead of
   three loose groups sitting on the page. */
#px-d-grid.dl-sidebar-left #px-d-convohead{
  margin:0;padding:11px 0 0;
  letter-spacing:.14em;
  color:color-mix(in srgb,var(--ink) 50%,transparent);
}
#px-d-grid.dl-sidebar-left #px-d-bar{
  margin:9px 0 4px;padding:0 0 12px;
  border-bottom:1px solid var(--line);
}
#px-d-grid.dl-sidebar-left #px-d-actions-top button,
#px-d-grid.dl-sidebar-left #px-d-actions-top a{
  border-radius:4px;
}
/* ── THE SEARCH FIELD ─────────────────────────────────────────────────────────────────────────
   ⚠ THE WRAPPER IS THE FIELD, THE INPUT IS JUST TEXT. `.d-search` already carries a border, a
   background and a radius, and the <input> inside it picks up the global input styling — border,
   background, padding and a radius of its own — so the control rendered as a field drawn inside a
   field. The inner control is stripped back to bare text; the wrapper is the only field.

   The finish is built from depth rather than from roundness, to stay in this layout's register: a
   squared 4px corner, a lit top edge, a soft cast shadow, and an accent that only appears on focus.
   Every value is mixed from --card / --ink / --accent / --line. */
#px-d-search{
  display:flex;align-items:center;gap:10px;
  min-height:40px;padding:0 13px;
  border-radius:4px;
  background:linear-gradient(
    color-mix(in srgb,var(--card) 100%,transparent),
    color-mix(in srgb,var(--ink) 2%,var(--card)));
  border:1px solid color-mix(in srgb,var(--ink) 12%,var(--line));
  box-shadow:
    inset 0 1px 0 color-mix(in srgb,var(--card) 90%,transparent),
    inset 0 1px 2px color-mix(in srgb,var(--ink) 4%,transparent),
    0 1px 2px color-mix(in srgb,var(--ink) 4%,transparent);
  transition:border-color .18s var(--ease,ease), box-shadow .18s var(--ease,ease),
             background .18s var(--ease,ease);
}
#px-d-search:hover{
  border-color:color-mix(in srgb,var(--ink) 20%,var(--line));
}
/* Focus lights the whole control once, on the wrapper — never a second ring on the input. */
#px-d-search:focus-within{
  background:var(--card);
  border-color:color-mix(in srgb,var(--accent) 58%,var(--line));
  box-shadow:
    inset 0 1px 0 color-mix(in srgb,var(--card) 95%,transparent),
    0 0 0 3px color-mix(in srgb,var(--accent) 15%,transparent),
    0 2px 6px -2px color-mix(in srgb,var(--accent) 26%,transparent);
}
/* The icon is a quiet mark that takes the accent only while the field is live. */
#px-d-search > svg{
  flex:0 0 auto;display:block;
  color:color-mix(in srgb,var(--ink) 40%,transparent);
  transition:color .18s var(--ease,ease), transform .18s var(--ease,ease);
}
/* The mark takes the accent and leans in a touch when the field goes live. */
#px-d-search:focus-within > svg{
  color:var(--accent);
  transform:scale(1.06);
}
/* The caret and the selection belong to the theme too — a default black caret and a browser-blue
   selection are the two details that give away an otherwise themed field. */
#px-d-search > #px-d-q{caret-color:var(--accent)}
#px-d-search > #px-d-q::selection{
  background:color-mix(in srgb,var(--accent) 24%,transparent);
  color:var(--ink);
}
/* Chrome draws its own grey clear button inside search inputs, which puts a second control back
   inside the field we just finished flattening. */
#px-d-search > #px-d-q::-webkit-search-cancel-button,
#px-d-search > #px-d-q::-webkit-search-decoration{-webkit-appearance:none;appearance:none}
#px-d-search > #px-d-q{
  flex:1 1 auto;min-width:0;
  border:0;background:none;box-shadow:none;outline:none;
  border-radius:0;padding:0;margin:0;height:auto;min-height:0;
  font:inherit;font-size:13px;letter-spacing:.005em;
  color:var(--ink);
}
#px-d-search > #px-d-q:focus,
#px-d-search > #px-d-q:focus-visible{
  border:0;box-shadow:none;outline:none;background:none;
}
#px-d-search > #px-d-q::placeholder{
  color:color-mix(in srgb,var(--ink) 38%,transparent);
  letter-spacing:.01em;
}
/* The hit count reads as a tally, not as prose: tabular, boxed, quiet. */
#px-d-search > #px-d-q-count{
  flex:0 0 auto;
  font-size:10.5px;font-weight:800;font-variant-numeric:tabular-nums;letter-spacing:.04em;
  color:color-mix(in srgb,var(--ink) 55%,transparent);
  background:color-mix(in srgb,var(--ink) 6%,transparent);
  border-radius:3px;padding:2px 7px;
}
#px-d-search > #px-d-q-count:empty{display:none}

/* Narrow: the measure and the mirroring both stop paying for themselves. */
@media(max-width:640px){
  #px-d-grid.dl-sidebar-left .thread .brow,
  #px-d-grid.dl-sidebar-left .thread .brow.mine,
  #px-d-grid.dl-sidebar-left .thread .brow:not(.mine){
    max-width:100%;margin-left:0;margin-right:0;
    grid-template-columns:32px minmax(0,1fr);
  }
  #px-d-grid.dl-sidebar-left .thread .brow .bubble{grid-column:2}
  #px-d-grid.dl-sidebar-left .thread .brow:not(.mine) .avat{grid-column:1}
  #px-d-grid.dl-sidebar-left .thread .brow:not(.mine) .bubble > .who{grid-column:1;text-align:left}
  #px-d-grid.dl-sidebar-left .thread .brow:not(.mine) .bubble > .at{grid-column:2;text-align:right}
  #px-d-grid.dl-sidebar-left .thread .avat{width:28px;height:28px;border-radius:6px}
}
  /* ⚠ dl-print-friendly REMOVED FROM BOTH HALVES. It used to be forced to one column and to unpin
     its side cards — but the unpin was written with three classes and lost to
     `#px-d-grid.dss-sticky.dss-tall .rq-side > .side-card{position:sticky}` (one id + three), so it
     never applied and the "flat" layout still had a pinned sidebar. It now takes a real column and
     pins like the rest, and the sticky-mode machinery governs it. */
  /* ⚠ `.rq-grid.dl-single-column{grid-template-columns:1fr}` WAS HERE and is deliberately gone.
     It was the pre-redesign one-column geometry, dead for a long time because a stray `}` above
     swallowed it into a prelude — and reviving it (brace fixed 2026-08-02) only revived a
     contradiction: dl-single-column is now the two-column CASE FILE — search `#px-d-grid.dl-single-
     column{` for it, do not trust a line number. The id form outranked it (1,1,0) vs
     (0,2,0) so the real grid never collapsed, but any element carrying `rq-grid dl-single-column`
     WITHOUT the id — a Studio preview mock, say — would have. This layout's geometry lives with the
     case file, NOT in this family block; do not re-add a `.rq-grid.dl-single-column` width rule. */
  .dl-single-column .rq-side .side-card{position:static}
  .dl-single-column .rq-side,.dl-tabs .rq-side{order:2}
  .rq-grid.dl-wide{grid-template-columns:minmax(0,1fr) 340px}

  .rq-grid.dl-tabs{grid-template-columns:1fr}.dl-tabs .rq-side{display:none}
  /* ADDITIVE_PORTAL_PREMIUM_2026 — additional ticket-detail compositions. */
  .d-tabs{display:flex;gap:6px;margin-bottom:14px;border-bottom:1px solid var(--line)}
  .d-tabs button{background:none;border:none;padding:8px 4px;margin-right:14px;font-size:13.5px;font-weight:700;color:var(--ink-3);cursor:pointer;border-bottom:2px solid transparent;margin-bottom:-1px}
  .d-tabs button.on{color:var(--accent);border-bottom-color:var(--accent)}
  /* SP3 — attachments v2 */
  .att-chip{display:inline-flex;align-items:center;gap:7px;background:var(--card);border:1px solid var(--line);padding:6px 10px;border-radius:10px;color:var(--ink-2)}
  .att-chip img{width:26px;height:26px;object-fit:cover;border-radius:6px}
  .att-chip .ax{cursor:pointer;color:var(--ink-3);font-weight:800;padding:0 2px}
  .att-chip .ax:hover{color:var(--err)}
  .att-chip .asz{color:var(--ink-3);font-size:10.5px}
  .att-row.ap-compact .att-chip img{display:none}
  .att-row.ap-list{display:flex;flex-direction:column;align-items:stretch}
  .att-row.ap-list .att-chip{width:100%;justify-content:flex-start}
  .att-row.ap-list .att-chip .ax{margin-left:auto}
  .px-att-error{font-size:12.5px;color:var(--err);margin-top:8px;line-height:1.45}
  .px-upload{display:flex;align-items:center;gap:10px;margin-top:10px;font-size:12px;font-weight:700;color:var(--ink-3)}
  .px-upload-track{height:7px;flex:1;background:var(--line-soft);border-radius:999px;overflow:hidden}
  .px-upload-track i{display:block;width:0;height:100%;background:var(--accent);border-radius:inherit;transition:width .14s linear}
  .px-retry{position:relative;display:grid;grid-template-columns:auto minmax(0,1fr) auto;align-items:center;gap:14px;margin-top:14px;padding:16px;border:1px solid color-mix(in srgb,var(--err) 24%,var(--line));background:linear-gradient(135deg,color-mix(in srgb,var(--err) 8%,var(--card)),var(--card) 68%);border-radius:16px;box-shadow:0 16px 36px -28px color-mix(in srgb,var(--err) 78%,transparent),inset 0 1px rgba(255,255,255,.55);overflow:hidden}
  .px-retry::before{content:'';position:absolute;inset:0 auto 0 0;width:3px;background:linear-gradient(180deg,var(--err),color-mix(in srgb,var(--err) 55%,var(--accent)))}
  .px-retry-icon{width:42px;height:42px;border-radius:13px;display:grid;place-items:center;color:var(--err);background:color-mix(in srgb,var(--err) 11%,var(--card));border:1px solid color-mix(in srgb,var(--err) 19%,var(--line));box-shadow:0 8px 18px -14px var(--err)}
  .px-retry-icon svg{width:20px;height:20px}
  .px-retry-copy{display:flex;flex-direction:column;gap:3px;min-width:0}
  .px-retry-copy strong{font-size:13.5px;line-height:1.25;color:var(--ink);letter-spacing:-.005em}
  .px-retry-copy span{font-size:12.25px;line-height:1.5;color:var(--ink-3)}
  .px-retry-actions{display:flex;align-items:center;gap:7px}
  .px-retry-actions button{flex:none;min-height:36px;padding:8px 13px;border-radius:10px;font-size:12px;font-weight:800;cursor:pointer;transition:transform .15s var(--ease),box-shadow .15s var(--ease),background .15s var(--ease)}
  .px-retry-primary{border:1px solid transparent;color:#fff;background:linear-gradient(135deg,var(--accent),var(--accent-d));box-shadow:0 9px 18px -11px var(--accent)}
  .px-retry-primary:hover{transform:translateY(-1px);box-shadow:0 12px 24px -12px var(--accent)}
  .px-retry-secondary{border:1px solid var(--line);color:var(--ink-2);background:color-mix(in srgb,var(--card) 82%,transparent)}
  .px-retry-secondary:hover{background:var(--line-soft);color:var(--ink)}
  .brow.px-send-pending{opacity:.72}.brow.px-send-failed{opacity:1}
  .brow.px-send-failed .bubble{border-color:color-mix(in srgb,var(--err) 34%,var(--line))!important;box-shadow:0 12px 28px -24px var(--err)!important}
  .px-send-state{display:inline-flex;align-items:center;gap:6px;width:max-content;margin-top:8px;padding:4px 8px;border-radius:999px;background:var(--line-soft);font-size:10.5px;font-weight:850;line-height:1;color:var(--ink-3);letter-spacing:.015em}
  .px-send-state::before{content:'';width:6px;height:6px;border-radius:50%;background:currentColor;box-shadow:0 0 0 3px color-mix(in srgb,currentColor 12%,transparent)}
  .px-send-pending .px-send-state::before{animation:pxSendPulse 1.1s ease-in-out infinite}
  .brow.px-send-failed .px-send-state{color:var(--err);background:color-mix(in srgb,var(--err) 9%,var(--card))}
  @keyframes pxSendPulse{50%{opacity:.35;transform:scale(.8)}}
  @media(max-width:760px){.px-retry{grid-template-columns:auto 1fr}.px-retry-actions{grid-column:1/-1}.px-retry-actions button{flex:1}}
  .dropzone{border:1.5px dashed var(--line);border-radius:13px;padding:11px;text-align:center;font-size:12.5px;color:var(--ink-3);margin-top:10px;transition:.15s var(--ease);cursor:pointer}
  .dropzone.on,.dropzone:hover{border-color:var(--accent);color:var(--accent);background:color-mix(in srgb,var(--accent) 4%,transparent)}
  /* SP3 — draft restore banner */
  .draftbar{display:flex;align-items:center;gap:10px;background:color-mix(in srgb,var(--accent) 6%,var(--line-soft));border:1px solid color-mix(in srgb,var(--accent) 18%,var(--line));border-radius:12px;padding:10px 14px;font-size:13px;color:var(--ink-2);margin-bottom:14px;animation:pdIn .25s ease}
  .draftbar .link{margin:0}
  .draftbar .link+.link{margin-left:8px}
  /* SP3b — CSAT stars */
  .csat-stars button{background:none;border:none;font-size:26px;line-height:1;cursor:pointer;color:var(--line);transition:transform .12s var(--ease),color .12s var(--ease);padding:2px}
  .csat-stars button.on{color:#f59e0b}
  .csat-stars button:hover{transform:scale(1.15)}
  /* SP3 — SLA expected-reply pill */
  .slahint{display:inline-flex;align-items:center;gap:7px;background:#ecfdf5;border:1px solid #bbf7d0;color:#047857;font-size:12.5px;font-weight:700;border-radius:999px;padding:5px 13px;margin-top:12px}
  /* ═══ SP4b — mature ticket-system IA: pages, breadcrumbs, table, sidebar ═══ */
  .pxpage{animation:pdIn .22s ease}
  #px-wrap{max-width:980px}
  #pg-new .card,#pg-status .card{max-width:680px}
  .crumbs{display:flex;align-items:center;gap:8px;font-size:12.5px;color:var(--ink-2);margin:4px 0 10px}
  .crumbs a{color:var(--ink-2);text-decoration:none;font-weight:650}
  /* PHASE_PORTAL_P21 — touch targets on phones/tablets (plan bar: ≥44px).
     Measured at 375px: the action buttons all sat at 38–42px (a few px short) and the
     breadcrumb links at just 19px, well under half.
     ⚠ THE BUTTONS AND THE LINKS NEED DIFFERENT TREATMENTS. `min-height` is right for a
     button, but padding a breadcrumb out to 44px would turn a one-line trail into a slab.
     The crumbs instead get an INVISIBLE hit area via ::after — the tap target reaches 45px
     while the text keeps its 19px line box, so nothing moves visually. It expands only
     vertically (left/right pinned to the link), so adjacent crumbs cannot steal each
     other's taps. This is the standard technique and the only one that satisfies the bar
     without redesigning the trail. */
  @media(max-width:760px){
    .btn,.btn-ghost,.rowbtns button,.px-acct-btn,.d-reply-top,.px-skip,
    .reqfilters button,.link{min-height:44px}
    /* Same reasoning as the crumbs: `.idchip .idedit` ("Not you?") is a small text button
       sitting INSIDE the signed-in-as chip — a min-height would stretch the chip itself. */
    .crumbs a,.idchip .idedit{position:relative}
    .crumbs a::after,.idchip .idedit::after{content:"";position:absolute;left:0;right:0;top:-13px;bottom:-13px}
  }
  .crumbs a:hover{color:var(--accent)}
  .pgtitle{margin:0 0 16px;font-size:24px;font-weight:850;letter-spacing:-.02em;color:var(--ink)}
  .pgtitle-row{display:flex;align-items:center;justify-content:space-between;gap:12px;flex-wrap:wrap;margin-bottom:14px}
  .pgtitle-row .pgtitle{margin:0}
  .btn-inline{width:auto;margin-top:0;padding:11px 20px;font-size:13.5px}
  .homecta{display:grid;grid-template-columns:1fr 1fr;gap:14px;margin-top:8px}
  @media(max-width:640px){.homecta{grid-template-columns:1fr}}
  .cta-card{display:flex;align-items:center;gap:14px;background:var(--card);border:1px solid var(--line);border-radius:15px;padding:18px;text-decoration:none;box-shadow:0 1px 2px rgba(15,23,42,.04);transition:transform .18s var(--ease),box-shadow .18s var(--ease),border-color .18s var(--ease)}
  .cta-card:hover{transform:translateY(-2px);box-shadow:var(--shadow-md);border-color:color-mix(in srgb,var(--accent) 30%,var(--line))}
  .cta-ic{flex-shrink:0;width:44px;height:44px;display:flex;align-items:center;justify-content:center;border-radius:13px;background:color-mix(in srgb,var(--accent) 9%,var(--line-soft));color:var(--accent)}
  .cta-tx{flex:1;display:flex;flex-direction:column;gap:2px}
  .cta-tx b{font-size:14.5px;color:var(--ink)}
  .cta-tx i{font-style:normal;font-size:12.5px;color:var(--ink-3)}
  .cta-card .pcatr-arr{color:var(--ink-3)}
  .cta-card:hover .pcatr-arr{transform:translateX(3px);color:var(--accent)}
  /* ═══ W6 — department picker (10 styles + My-tickets rail) ═══ */
  .dp-wrap{display:block}
  .dp-wrap.has-rail{display:grid;grid-template-columns:260px minmax(0,1fr);gap:22px;align-items:start}
  .dp-wrap.has-rail.rail-right{grid-template-columns:minmax(0,1fr) 260px}
  .dp-wrap.has-rail.rail-right .dp-rail{order:2}
  @media(max-width:760px){.dp-wrap.has-rail,.dp-wrap.has-rail.rail-right{grid-template-columns:1fr}}
  .dp-rail{padding:18px 16px;position:sticky;top:calc(var(--px-navh,0px) + 13px)}
  .px-greet-home{max-width:var(--px-page-w,1320px);margin:0 auto;padding:22px 20px 0}
  .px-greet-home.hidden{display:none}
  .rq-rail-extra{display:flex;flex-direction:column}
  .dp-rail-title{font-size:15px;font-weight:850;letter-spacing:-.02em;margin:0 0 13px;padding-bottom:12px;border-bottom:1px solid var(--line)}
  .dp-rail-link{display:flex;align-items:center;gap:10px;padding:10px 12px;border-radius:10px;text-decoration:none;font-weight:700;font-size:13.5px;color:var(--ink-2);transition:.14s var(--ease)}
  .dp-rail-link svg{color:var(--accent)}
  /* Icon-font links (Font Awesome etc.) sit in the same 17px slot as the inline SVGs, so a
     mixed list still lines up down the left edge. */
  .dp-rail-link i{color:var(--accent);font-size:15px;width:17px;text-align:center;flex:none}
  .dp-rail-link:hover{background:color-mix(in srgb,var(--accent) 7%,transparent);color:var(--accent)}
  .dp-rail-cta{color:var(--accent)}
  .dp-ic{flex-shrink:0;width:46px;height:46px;display:flex;align-items:center;justify-content:center;font-size:22px;border-radius:13px;background:color-mix(in srgb,var(--accent) 9%,var(--line-soft))}
  .dp-nm{font-weight:800;font-size:15px;color:var(--ink);display:flex;align-items:center;gap:7px;flex-wrap:wrap;min-width:0}
  .dp-ds{font-size:13px;color:var(--ink-3);line-height:1.45;margin-top:3px;display:block}
  .dp-lock{font-size:12px}
  .dp-badges{display:inline-flex;align-items:center;gap:5px;flex-wrap:wrap;margin-left:2px;min-width:0;max-width:100%}
  .dp-badge{display:inline-flex;align-items:center;min-height:20px;padding:3px 7px;border-radius:999px;font-size:9.5px;font-weight:850;line-height:1;letter-spacing:.025em;text-transform:uppercase;white-space:nowrap}
  .dp-badges.dbs-soft .dp-badge{background:color-mix(in srgb,var(--accent) 9%,var(--line-soft));color:var(--accent)}
  .dp-badges.dbs-outline .dp-badge{background:transparent;color:var(--ink-2);border:1px solid color-mix(in srgb,var(--accent) 30%,var(--line))}
  .dp-badges.dbs-solid .dp-badge{background:var(--accent);color:#fff}
  .dp-badge.dp-access{color:#b45309!important;background:color-mix(in srgb,#f59e0b 13%,var(--card))!important}
  .px-flow-progress{display:flex;align-items:center;gap:9px;margin:0 0 14px;padding:12px 14px;border:1px solid color-mix(in srgb,var(--accent) 18%,var(--line));border-radius:13px;background:linear-gradient(135deg,color-mix(in srgb,var(--accent) 7%,var(--card)),var(--card));font-size:11.5px;font-weight:800;color:var(--ink-3)}
  .px-flow-progress .pf-step{display:inline-flex;align-items:center;gap:6px}.px-flow-progress .pf-step b{width:22px;height:22px;display:grid;place-items:center;border-radius:50%;background:var(--line-soft);color:var(--ink-3);font-size:10px}
  .px-flow-progress .pf-step.done{color:var(--ok)}.px-flow-progress .pf-step.done b{background:color-mix(in srgb,var(--ok) 14%,transparent);color:var(--ok)}
  .px-flow-progress .pf-step.now{color:var(--accent)}.px-flow-progress .pf-step.now b{background:var(--accent);color:#fff}
  .px-flow-progress .pf-line{height:1px;flex:1;max-width:34px;background:color-mix(in srgb,var(--accent) 28%,var(--line))}
  .px-flow-progress .pf-change{margin-left:auto;border:0;background:transparent;color:var(--accent);font:inherit;cursor:pointer;padding:4px}
  #p-new-form .px-invalid{border-color:var(--err)!important;box-shadow:0 0 0 3px color-mix(in srgb,var(--err) 11%,transparent)!important}
  @media(max-width:560px){.px-flow-progress{flex-wrap:wrap}.px-flow-progress .pf-change{width:100%;text-align:left;margin-left:28px}}
  .dp-arr{color:var(--ink-3);transition:transform .16s var(--ease),color .16s var(--ease);flex-shrink:0}
  /* cards / grid */
  .dp-cards{display:grid;gap:14px}.dp-g{grid-template-columns:repeat(auto-fill,minmax(280px,1fr))}.dp-g2{grid-template-columns:repeat(2,minmax(0,1fr))}.dp-g3{grid-template-columns:repeat(3,minmax(0,1fr))}.dp-g4{grid-template-columns:repeat(4,minmax(0,1fr))}
  /* PHASE_PORTAL_DEPT — department filter box */
  .dp-search{margin-bottom:14px}
  .dp-search input{width:100%;padding:12px 15px;border:1px solid var(--line);border-radius:12px;background:var(--card);color:var(--ink);font-size:14px;font-family:inherit}
  .dp-search input:focus{outline:none;border-color:var(--accent)}
  @media(max-width:640px){.dp-g2,.dp-g3{grid-template-columns:1fr}}
  .dp-card{display:flex;align-items:center;gap:14px;min-width:0;max-width:100%;text-align:left;background:var(--card);border:1px solid var(--line);border-radius:16px;padding:18px;cursor:pointer;transition:transform .18s var(--ease),box-shadow .18s var(--ease),border-color .18s var(--ease)}
  .dp-card:hover{transform:translateY(-3px);box-shadow:var(--shadow-md);border-color:color-mix(in srgb,var(--accent) 32%,var(--line))}
  .dp-card:hover .dp-arr{transform:translateX(3px);color:var(--accent)}
  .dp-body{flex:1;min-width:0}
  /* list */
  .dp-list{display:flex;flex-direction:column;gap:8px}
  .dp-row{display:flex;align-items:center;gap:14px;text-align:left;background:var(--card);border:1px solid var(--line);border-radius:13px;padding:14px 16px;cursor:pointer;transition:border-color .16s var(--ease),transform .16s var(--ease)}
  .dp-row:hover{border-color:color-mix(in srgb,var(--accent) 32%,var(--line));transform:translateX(2px)}
  .dp-row .dp-tx{flex:1}.dp-row:hover .dp-arr{color:var(--accent);transform:translateX(2px)}
  /* COMPACT LIST — icon + name only, in one bordered block with hairline
     dividers instead of separate cards. For the common case of a handful of
     departments, where badges and descriptions are noise. */
  .dp-list-compact{gap:0;border:1px solid var(--line);border-radius:var(--r-lg,14px);background:var(--card);overflow:hidden}
  /* --line-soft is tuned for large quiet surfaces and vanishes as a 1px rule
     between rows, so the compact list derives its own divider from --ink. */
  .dp-list-compact .dp-row{border:0;border-bottom:1px solid color-mix(in srgb,var(--ink) 13%,transparent);border-radius:0;
    padding:13px 16px;gap:11px;background:transparent}
  .dp-list-compact .dp-row:last-child{border-bottom:0}
  /* TWO PER ROW — same compact row, two columns. The vertical rule between the
     pair comes from the odd cell; the last row drops its bottom rule, and with
     an ODD number of departments the final cell spans both columns so the block
     never ends with a half-empty gap. */
  .dp-list-compact.dp-lc2{display:grid;grid-template-columns:1fr 1fr}
  .dp-list-compact.dp-lc2 .dp-row:nth-child(odd){border-right:1px solid color-mix(in srgb,var(--ink) 13%,transparent)}
  .dp-list-compact.dp-lc2 .dp-row:nth-last-child(-n+2){border-bottom:0}
  .dp-list-compact.dp-lc2 .dp-row:nth-last-child(2):nth-child(odd){border-bottom:1px solid color-mix(in srgb,var(--ink) 13%,transparent)}
  .dp-list-compact.dp-lc2 .dp-row:last-child:nth-child(odd){grid-column:1/-1;border-right:0}
  @media(max-width:640px){.dp-list-compact.dp-lc2{grid-template-columns:1fr}
    .dp-list-compact.dp-lc2 .dp-row{border-right:0!important}}
  .dp-list-compact .dp-row:hover{transform:none;background:color-mix(in srgb,var(--accent) 5%,transparent)}
  .dp-list-compact .dp-nm{font-size:14.5px;font-weight:650}
  /* the icon tile shrinks to a glyph so the row stays one line tall */
  .dp-list-compact .dp-ic{width:22px;height:22px;border-radius:6px;background:transparent;color:var(--accent)}
  .dp-list-compact .dp-ic svg{width:17px;height:17px}

  /* ── SUPPORT HOURS CARD (department picker rail) ─────────────────────────
     Surface, radius and type all ride the design tokens, so a Studio brand or
     radius change carries. The two badge colours are operator settings with a
     neutral fallback — the renderer sets them inline when chosen. */
  .dp-hours{margin-top:14px;padding:16px 16px 14px;border:1px solid var(--line);border-radius:var(--r-lg,16px);background:var(--card)}
  .dp-hours-t{font-size:14px;font-weight:800;letter-spacing:-.01em;color:var(--ink);margin-bottom:10px;
    padding-bottom:10px;border-bottom:1px solid var(--line-soft,var(--line))}
  .dp-hours-time{font-size:17px;font-weight:750;color:var(--ink);letter-spacing:-.01em}
  .dp-hours-days{margin-top:3px;font-size:12.5px;font-weight:650;color:var(--ink-2)}
  .dp-hours-tz{margin-top:2px;font-size:12px;color:var(--ink-3)}
  .dp-hours-badge{display:block;margin-top:12px;padding:9px 12px;border-radius:var(--r-md,10px);
    text-align:center;font-size:11.5px;font-weight:850;letter-spacing:.08em;color:#fff}
  .dp-hours-badge.is-open{background:#16a34a}
  .dp-hours-badge.is-closed{background:#dc2626}
  .dp-hours-note{margin-top:8px;font-size:12.5px;line-height:1.5;color:var(--ink-3)}
  /* pills */
  /* ── ULTRA GLASS TILES (grid-4) ──────────────────────────────────────────
     Frosted glass only reads as glass when there is something BEHIND it, so the
     grid paints its own field of soft brand-tinted orbs and the tiles float on
     top of it. Every colour derives from --accent/--ink, so this follows the
     workspace brand rather than shipping a fixed purple. */
  /* No outer panel: the tiles sit directly on the page. The frosted effect
     still works because backdrop-filter blurs whatever the PAGE background is,
     so the glass picks up the operator's own backdrop instead of a field this
     style painted for itself. */
  .dp-tiles{display:grid;grid-template-columns:repeat(4,1fr);gap:16px}
  .dp-tile{position:relative;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:13px;
    min-height:142px;padding:22px 12px;text-align:center;cursor:pointer;overflow:hidden;
    border:1px solid color-mix(in srgb,#fff 55%,transparent);
    border-radius:calc(var(--r-lg,14px) + 4px);
    background:linear-gradient(150deg, color-mix(in srgb,#fff 62%,transparent), color-mix(in srgb,#fff 26%,transparent));
    -webkit-backdrop-filter:blur(18px) saturate(180%);
            backdrop-filter:blur(18px) saturate(180%);
    box-shadow:inset 0 1px 0 rgba(255,255,255,.9),inset 0 -18px 34px -22px color-mix(in srgb,var(--accent) 55%,transparent),
               0 2px 6px -2px rgba(2,6,23,.14),0 16px 34px -16px color-mix(in srgb,var(--accent) 45%,transparent);
    transition:transform .28s cubic-bezier(.2,.8,.2,1),box-shadow .28s var(--ease),border-color .28s var(--ease)}
  /* a light sweep that crosses the glass on hover */
  .dp-tile::after{content:'';position:absolute;top:0;left:-60%;width:45%;height:100%;pointer-events:none;
    background:linear-gradient(100deg,transparent,rgba(255,255,255,.55),transparent);
    transform:skewX(-18deg);transition:left .55s cubic-bezier(.2,.8,.2,1)}
  .dp-tile:hover::after{left:120%}
  .dp-tile:hover{transform:translateY(-6px) scale(1.015);
    border-color:color-mix(in srgb,#fff 80%,transparent);
    box-shadow:inset 0 1px 0 rgba(255,255,255,1),inset 0 -22px 40px -22px color-mix(in srgb,var(--accent) 65%,transparent),
               0 4px 10px -3px rgba(2,6,23,.16),0 30px 56px -20px color-mix(in srgb,var(--accent) 60%,transparent)}
  .dp-tile:active{transform:translateY(-2px) scale(1.005)}

  /* the icon floats above the glass with its own coloured glow */
  .dp-tile-ic{position:relative;display:flex;align-items:center;justify-content:center;width:52px;height:52px;
    border-radius:16px;color:#fff;
    background:linear-gradient(160deg,color-mix(in srgb,var(--accent) 92%,#fff),color-mix(in srgb,var(--accent) 62%,var(--ink)));
    box-shadow:inset 0 1px 0 rgba(255,255,255,.55),inset 0 -2px 6px rgba(2,6,23,.28),
               0 8px 18px -6px color-mix(in srgb,var(--accent) 70%,transparent);
    transition:transform .28s cubic-bezier(.2,.8,.2,1),box-shadow .28s var(--ease)}
  .dp-tile:hover .dp-tile-ic{transform:translateY(-3px) scale(1.06) rotate(-3deg);
    box-shadow:inset 0 1px 0 rgba(255,255,255,.7),0 14px 26px -8px color-mix(in srgb,var(--accent) 80%,transparent)}
  .dp-tile-ic svg{width:23px;height:23px}
  .dp-tile-ic .dp-ic{width:52px;height:52px;background:transparent;color:#fff}
  .dp-tile-nm{font-size:13.5px;font-weight:750;line-height:1.35;color:var(--ink);letter-spacing:-.01em}
  .dp-tile-lock{position:absolute;top:10px;right:11px;font-size:11px;opacity:.6}

  /* Dark: a white sheen would look like a scratch, and the glass tints to ink. */
  [data-theme="dark"] .dp-tile,.px-dark .dp-tile{
    border-color:color-mix(in srgb,#fff 14%,transparent);
    background:linear-gradient(150deg,color-mix(in srgb,#fff 12%,transparent),color-mix(in srgb,#fff 4%,transparent));
    box-shadow:inset 0 1px 0 rgba(255,255,255,.14),0 2px 6px -2px rgba(0,0,0,.5),0 18px 36px -16px rgba(0,0,0,.75)}
  [data-theme="dark"] .dp-tile::after,.px-dark .dp-tile::after{background:linear-gradient(100deg,transparent,rgba(255,255,255,.16),transparent)}

  /* Respect a reduced-motion preference: keep the depth, drop the movement. */
  @media(prefers-reduced-motion:reduce){
    .dp-tile,.dp-tile-ic{transition:none}
    .dp-tile:hover{transform:none}
    .dp-tile:hover .dp-tile-ic{transform:none}
    .dp-tile::after{display:none}
  }
  @media(max-width:860px){.dp-tiles{grid-template-columns:repeat(3,1fr)}}
  @media(max-width:640px){.dp-tiles{grid-template-columns:repeat(2,1fr)}}

  /* ── ICON COLUMN (icon-3) — NO card chrome at all. Icon on top, name, then
     the description. Three per row. For enterprises that want the information
     without the boxes. ─────────────────────────────────────────────────────── */
  .dp-icol{display:grid;grid-template-columns:repeat(3,1fr);gap:clamp(20px,2.6vw,40px)}
  .dp-icol-it{display:flex;flex-direction:column;align-items:center;gap:10px;padding:4px 0;
    background:none;border:0;text-align:center;cursor:pointer}
  .dp-icol-ic{display:flex;align-items:center;justify-content:center;width:38px;height:38px;border-radius:10px;
    background:color-mix(in srgb,var(--accent) 10%,transparent);color:var(--accent);transition:.16s var(--ease)}
  .dp-icol-ic svg{width:19px;height:19px}
  .dp-icol-ic .dp-ic{width:38px;height:38px;background:transparent}
  .dp-icol-nm{display:flex;align-items:center;justify-content:center;gap:8px;flex-wrap:wrap;font-size:15px;font-weight:750;color:var(--ink);letter-spacing:-.01em}
  .dp-icol-ds{max-width:34ch;font-size:13px;line-height:1.6;color:var(--ink-3)}
  .dp-icol-it:hover .dp-icol-nm{color:var(--accent)}
  .dp-icol-it:hover .dp-icol-ic{background:color-mix(in srgb,var(--accent) 18%,transparent)}
  @media(max-width:860px){.dp-icol{grid-template-columns:repeat(2,1fr)}}
  @media(max-width:640px){.dp-icol{grid-template-columns:1fr}}

  .dp-pills{display:flex;flex-wrap:wrap;gap:10px}
  /* inline-flex + auto width is what makes these read as CHIPS rather than as
     narrow cards; the icon shrinks to a glyph so the pill stays one line tall */
  .dp-pill{display:inline-flex;align-items:center;gap:9px;width:auto;background:var(--card);border:1px solid var(--line);border-radius:999px;padding:10px 18px;font-weight:700;font-size:14px;color:var(--ink);cursor:pointer;transition:.15s var(--ease)}
  .dp-pill-ic{display:inline-flex;align-items:center;justify-content:center;width:20px;height:20px;flex:none;color:var(--accent)}
  .dp-pill-ic svg{width:17px;height:17px}
  .dp-pill-ic .dp-ic{width:20px;height:20px;background:transparent;border-radius:0}
  .dp-pill-nm{white-space:nowrap}
  .dp-pill-lock{font-size:11px;opacity:.6}
  .dp-pill:hover{border-color:var(--accent);color:var(--accent);transform:translateY(-2px)}
  /* mega */
  .dp-mega{display:grid;gap:16px;grid-template-columns:repeat(auto-fill,minmax(240px,1fr))}
  .dp-mega-card{display:flex;flex-direction:column;gap:10px;text-align:left;background:var(--card);border:1px solid var(--line);border-radius:18px;padding:22px;cursor:pointer;transition:transform .18s var(--ease),box-shadow .18s var(--ease),border-color .18s var(--ease)}
  .dp-mega-card:hover{transform:translateY(-4px);box-shadow:var(--shadow-lg);border-color:color-mix(in srgb,var(--accent) 34%,var(--line))}
  .dp-mega-card .dp-cta{display:inline-flex;align-items:center;gap:6px;font-size:13px;font-weight:800;color:var(--accent);margin-top:4px}
  /* dropdown */
  /* ── DROPDOWN — a real listbox, heavily styled ───────────────────────────
     A native <option> cannot hold an icon, a description or a badge, so this
     renders its own panel and keeps a hidden <select> as the form value. */
  /* centred in the column — a 560px card left-aligned in a 1300px shell reads
     as a form that failed to load the rest of itself */
  .dp-dropcard{max-width:560px;margin-inline:auto;padding:clamp(20px,2.4vw,28px);border:1px solid var(--line);
    border-radius:calc(var(--r-lg,16px) + 4px);background:var(--card);
    box-shadow:0 1px 2px rgba(2,6,23,.05),0 18px 40px -28px rgba(2,6,23,.35)}
  .dp-dd-native{position:absolute;width:1px;height:1px;opacity:0;pointer-events:none}
  .dp-dd{position:relative}

  .dp-dd-btn{display:flex;align-items:center;justify-content:space-between;gap:12px;width:100%;
    min-height:60px;padding:12px 16px;cursor:pointer;text-align:left;
    border:1.5px solid var(--line);border-radius:var(--r-md,13px);
    background:linear-gradient(180deg,var(--card),color-mix(in srgb,var(--ink) 3%,var(--card)));
    box-shadow:inset 0 1px 0 rgba(255,255,255,.6);transition:border-color .16s var(--ease),box-shadow .16s var(--ease)}
  .dp-dd-btn:hover{border-color:color-mix(in srgb,var(--accent) 40%,var(--line))}
  .dp-dd.is-open .dp-dd-btn{border-color:var(--accent);
    box-shadow:0 0 0 4px color-mix(in srgb,var(--accent) 14%,transparent)}
  .dp-dd-cur{display:flex;align-items:center;gap:12px;min-width:0}
  .dp-dd-ph{font-size:14.5px;font-weight:600;color:var(--ink-3)}
  .dp-dd-curic{display:flex;align-items:center;justify-content:center;width:38px;height:38px;flex:none;
    border-radius:11px;color:#fff;
    background:linear-gradient(160deg,color-mix(in srgb,var(--accent) 92%,#fff),color-mix(in srgb,var(--accent) 62%,var(--ink)));
    box-shadow:0 5px 12px -5px color-mix(in srgb,var(--accent) 65%,transparent)}
  .dp-dd-curic svg{width:18px;height:18px}
  .dp-dd-curic .dp-ic{width:38px;height:38px;background:transparent;color:#fff}
  .dp-dd-curnm{font-size:15px;font-weight:750;color:var(--ink);letter-spacing:-.01em;
    overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  .dp-dd-caret{width:19px;height:19px;flex:none;color:var(--ink-3);transition:transform .2s var(--ease)}
  .dp-dd.is-open .dp-dd-caret{transform:rotate(180deg);color:var(--accent)}

  /* the panel floats over the page, scrolls past ~6 rows */
  .dp-dd-panel{position:absolute;z-index:40;top:calc(100% + 8px);left:0;right:0;
    max-height:340px;overflow:auto;overscroll-behavior:contain;padding:7px;
    border:1px solid var(--line);border-radius:var(--r-lg,16px);background:var(--card);
    box-shadow:0 12px 24px -12px rgba(2,6,23,.25),0 32px 60px -28px rgba(2,6,23,.45)}
  .dp-dd-panel[hidden]{display:none}
  /* ⚠ THE TWO SPELLINGS CANNOT BOTH BE SET. Chrome 121+ honours the STANDARD scrollbar-width /
     scrollbar-color in preference to ::-webkit-scrollbar, and its 'thin' bar arrives with the
     Windows arrow buttons at both ends — measured on the live portal, and not the small quiet
     bar this is meant to be. Firefox has no ::-webkit-scrollbar at all, so it gets the standard
     pair, fenced behind @supports where the pseudo-element does not exist. Same treatment as
     .px-lang .pnav-dd-menu in portal-core.css. */
  @supports not selector(::-webkit-scrollbar){
    .dp-dd-panel{scrollbar-width:thin;
      scrollbar-color:color-mix(in srgb,var(--accent) 45%,transparent) transparent}
  }
  /* WebKit scrollbar: a slim brand-tinted thumb inset from the panel edge, so
     the default chunky grey bar does not sit against the rounded corner. */
  .dp-dd-panel::-webkit-scrollbar{width:10px}
  .dp-dd-panel::-webkit-scrollbar-track{background:transparent;margin:8px 0}
  .dp-dd-panel::-webkit-scrollbar-thumb{
    background:color-mix(in srgb,var(--accent) 38%,transparent);
    border-radius:999px;border:3px solid transparent;background-clip:content-box}
  .dp-dd-panel::-webkit-scrollbar-thumb:hover{background:color-mix(in srgb,var(--accent) 62%,transparent);background-clip:content-box}
  .dp-dd-opt{display:flex;align-items:center;gap:12px;width:100%;padding:11px 12px;cursor:pointer;text-align:left;
    border:0;border-radius:var(--r-md,11px);background:transparent;transition:background .13s var(--ease)}
  .dp-dd-opt:hover,.dp-dd-opt:focus-visible{background:color-mix(in srgb,var(--accent) 8%,transparent);outline:none}
  .dp-dd-opt.is-sel{background:color-mix(in srgb,var(--accent) 12%,transparent)}
  .dp-dd-optic{display:flex;align-items:center;justify-content:center;width:36px;height:36px;flex:none;
    border-radius:10px;color:var(--accent);background:color-mix(in srgb,var(--accent) 12%,transparent)}
  .dp-dd-optic svg{width:18px;height:18px}
  .dp-dd-optic .dp-ic{width:36px;height:36px;background:transparent}
  .dp-dd-opt.is-sel .dp-dd-optic{color:#fff;
    background:linear-gradient(160deg,color-mix(in srgb,var(--accent) 92%,#fff),color-mix(in srgb,var(--accent) 62%,var(--ink)))}
  .dp-dd-opttx{display:flex;flex-direction:column;gap:2px;min-width:0;flex:1}
  .dp-dd-optnm{font-size:14px;font-weight:700;color:var(--ink)}
  .dp-dd-optds{font-size:12.5px;line-height:1.45;color:var(--ink-3)}
  .dp-dd-tick{width:17px;height:17px;flex:none;color:var(--accent);opacity:0;transition:opacity .13s var(--ease)}
  .dp-dd-opt.is-sel .dp-dd-tick{opacity:1}
  .dp-dd-opttx .dp-badges{margin-top:5px}
  .dp-dd-optds{max-width:100%}

  .dp-dropgo{width:100%;margin:16px 0 0;min-height:48px}
  .dp-dropgo.is-off{opacity:.45;cursor:not-allowed}
  @media(max-width:640px){.dp-dropcard{max-width:none}}
  /* ═══ W8 — LOOK PACKS: token-driven style systems for ticket surfaces ═══
     Scope = ticket pages only (home/design blocks untouched). radius+shadow are
     CSS vars (--tk-radius/--tk-shadow set inline by pxApplyLook); card/button/
     pill/density/motion are body classes. NOT per-option forks — one token set. */
  /* shared ticket-card selector group */
  body.tklook #pg-requests .card, body.tklook #pg-request .card, body.tklook #pg-new .card, body.tklook #pg-depts .card,
  body.tklook .px-tcard, body.tklook .kb-card, body.tklook .px-cozy-row{border-radius:var(--tk-radius,16px)}
  /* shadow token on the big surfaces */
  body.tklook #pg-requests>.card, body.tklook .rtable-wrap, body.tklook .px-tcard, body.tklook .px-cozy-row, body.tklook .kb-card, body.tklook #pg-request .rq-side .side-card{box-shadow:var(--tk-shadow,none)}
  body.tklook :is(#pg-requests,#pg-request,#pg-new,#pg-depts) :is(.btn,input,textarea,select,.rte-wrap){border-radius:calc(var(--tk-radius,12px) * .8)}
  /* ─ CARD STYLE (10) — restyle the ticket card group ─ */
  body.tkc-border .px-tcard, body.tkc-border .kb-card, body.tkc-border .px-cozy-row{box-shadow:none;border:1px solid var(--line)}
  body.tkc-shadow .px-tcard, body.tkc-shadow .kb-card, body.tkc-shadow .px-cozy-row{border-color:transparent;box-shadow:var(--tk-shadow,var(--shadow-md))}
  body.tkc-border-shadow .px-tcard, body.tkc-border-shadow .kb-card, body.tkc-border-shadow .px-cozy-row{border:1px solid var(--line);box-shadow:var(--tk-shadow,var(--shadow-sm))}
  body.tkc-flat .px-tcard, body.tkc-flat .kb-card, body.tkc-flat .px-cozy-row{border-color:transparent;box-shadow:none;background:var(--line-soft,color-mix(in srgb,var(--ink) 4%,transparent))}
  body.tkc-tinted .px-tcard, body.tkc-tinted .kb-card, body.tkc-tinted .px-cozy-row{background:color-mix(in srgb,var(--accent) 6%,var(--card));border-color:color-mix(in srgb,var(--accent) 16%,var(--line))}
  body.tkc-glass .px-tcard, body.tkc-glass .kb-card, body.tkc-glass .px-cozy-row{background:color-mix(in srgb,var(--card) 72%,transparent);backdrop-filter:blur(12px);border-color:color-mix(in srgb,#fff 30%,var(--line))}
  body.tkc-left-accent .px-tcard, body.tkc-left-accent .kb-card, body.tkc-left-accent .px-cozy-row{border-left:3px solid var(--accent)}
  body.tkc-underline-hover .px-tcard, body.tkc-underline-hover .kb-card, body.tkc-underline-hover .px-cozy-row{border:none;border-bottom:2px solid transparent;border-radius:0;box-shadow:none}
  body.tkc-underline-hover .px-tcard:hover, body.tkc-underline-hover .kb-card:hover, body.tkc-underline-hover .px-cozy-row:hover{border-bottom-color:var(--accent)}
  body.tkc-raised-hover .px-tcard, body.tkc-raised-hover .kb-card, body.tkc-raised-hover .px-cozy-row{transition:transform .18s var(--ease),box-shadow .18s var(--ease)}
  body.tkc-raised-hover .px-tcard:hover, body.tkc-raised-hover .kb-card:hover, body.tkc-raised-hover .px-cozy-row:hover{transform:translateY(-4px);box-shadow:var(--shadow-lg)}
  body.tkc-dashed .px-tcard, body.tkc-dashed .kb-card, body.tkc-dashed .px-cozy-row{border:1.5px dashed color-mix(in srgb,var(--accent) 45%,var(--line));box-shadow:none}
  /* ─ BUTTON STYLE (10) — ticket action buttons (scoped to ticket pages) ─ */
  body.tklook :is(#pg-requests,#pg-request,#pg-new,#pg-depts) .btn{transition:transform .15s var(--ease),box-shadow .15s var(--ease),filter .15s var(--ease)}
  body.tkb-solid :is(#pg-requests,#pg-request,#pg-new,#pg-depts) .btn{background:var(--accent);color:#fff}
  body.tkb-gradient :is(#pg-requests,#pg-request,#pg-new,#pg-depts) .btn{background:var(--accent-bg,linear-gradient(135deg,var(--accent),var(--accent-d)));color:#fff}
  body.tkb-soft :is(#pg-requests,#pg-request,#pg-new,#pg-depts) .btn{background:color-mix(in srgb,var(--accent) 15%,transparent);color:var(--accent);box-shadow:none}
  body.tkb-outline :is(#pg-requests,#pg-request,#pg-new,#pg-depts) .btn{background:transparent;color:var(--accent);border:1.5px solid var(--accent);box-shadow:none}
  body.tkb-outline-thick :is(#pg-requests,#pg-request,#pg-new,#pg-depts) .btn{background:transparent;color:var(--accent);border:2.5px solid var(--accent);box-shadow:none}
  body.tkb-ghost :is(#pg-requests,#pg-request,#pg-new,#pg-depts) .btn{background:transparent;color:var(--accent);box-shadow:none}
  body.tkb-ghost :is(#pg-requests,#pg-request,#pg-new,#pg-depts) .btn:hover{background:color-mix(in srgb,var(--accent) 10%,transparent)}
  body.tkb-glass :is(#pg-requests,#pg-request,#pg-new,#pg-depts) .btn{background:color-mix(in srgb,var(--accent) 28%,transparent);color:#fff;backdrop-filter:blur(8px);border:1px solid color-mix(in srgb,#fff 30%,transparent)}
  body.tkb-neumorphic :is(#pg-requests,#pg-request,#pg-new,#pg-depts) .btn{background:var(--card);color:var(--accent);box-shadow:6px 6px 12px color-mix(in srgb,var(--ink) 12%,transparent),-6px -6px 12px color-mix(in srgb,#fff 70%,transparent)}
  body.tkb-underline :is(#pg-requests,#pg-request,#pg-new,#pg-depts) .btn{background:transparent;color:var(--accent);border-radius:0;border-bottom:2px solid var(--accent);box-shadow:none;padding-left:4px;padding-right:4px;width:auto}
  body.tkb-pill-shadow :is(#pg-requests,#pg-request,#pg-new,#pg-depts) .btn{background:var(--accent-bg,var(--accent));color:#fff;border-radius:999px;box-shadow:0 10px 24px -6px color-mix(in srgb,var(--accent) 60%,transparent)}
  /* ─ PILL STYLE (10) — status pills, all consume --pc ─ */
  body.tkp-solid .pill{background:var(--pc);color:#fff;border-color:transparent}
  body.tkp-outline .pill{background:transparent;color:var(--pc);border:1.5px solid var(--pc)}
  body.tkp-dot-text .pill{background:transparent;border-color:transparent;color:var(--pc);padding-left:2px}
  body.tkp-dot-text .pill::before{content:"";display:inline-block;width:7px;height:7px;border-radius:50%;background:var(--pc);margin-right:6px;vertical-align:middle}
  body.tkp-dot-only .pill{font-size:0;background:transparent;border-color:transparent;padding:6px 3px}
  body.tkp-dot-only .pill::before{content:"";display:inline-block;width:10px;height:10px;border-radius:50%;background:var(--pc)}
  body.tkp-left-border .pill{background:color-mix(in srgb,var(--pc) 10%,transparent);border:none;border-left:3px solid var(--pc);border-radius:4px;color:var(--pc)}
  body.tkp-badge .pill{border-radius:5px;background:var(--pc);color:#fff;border-color:transparent;text-transform:uppercase;font-size:10.5px;letter-spacing:.05em}
  body.tkp-glow .pill{background:color-mix(in srgb,var(--pc) 16%,transparent);color:var(--pc);border-color:transparent;box-shadow:0 0 0 1px color-mix(in srgb,var(--pc) 35%,transparent),0 4px 12px -2px color-mix(in srgb,var(--pc) 45%,transparent)}
  body.tkp-mono .pill{background:transparent;color:var(--ink-2);border:1px solid var(--line);font-family:ui-monospace,monospace;text-transform:none}
  body.tkp-uppercase-tracked .pill{text-transform:uppercase;letter-spacing:.12em;font-size:10px;font-weight:900}
  /* ─ PHASE_PORTAL_TKGROUP — grouped list section headers ─ */
  .tl-grp{margin-bottom:22px}
  .tl-grp-h{display:flex;align-items:center;gap:9px;font-size:12.5px;font-weight:800;text-transform:uppercase;letter-spacing:.05em;color:var(--ink-2);margin:0 0 10px;padding-bottom:7px;border-bottom:1px solid var(--line)}
  .tl-grp-c{font-size:11.5px;font-weight:800;color:var(--accent);background:color-mix(in srgb,var(--accent) 12%,transparent);padding:1px 8px;border-radius:999px}
  /* ─ PHASE_PORTAL_TABLE2 — sticky header + first column (opt-in) ─ */
  body.tksticky .rtable thead th{position:sticky;top:0;z-index:3;background:var(--card)}
  body.tksticky .rtable tbody td:first-child,body.tksticky .rtable thead th:first-child{position:sticky;left:0;z-index:2;background:var(--card)}
  body.tksticky .rtable thead th:first-child{z-index:4}
  /* ─ PHASE_PORTAL_TKLIST — TABLE STYLE (5): lines | zebra | bordered | clean | card-rows ─ */
  body.tktbl-lines .rtable tbody tr{border-bottom:1px solid var(--line-soft)}
  body.tktbl-zebra .rtable tbody tr:nth-child(even){background:color-mix(in srgb,var(--ink) 3%,transparent)}
  body.tktbl-zebra .rtable tbody tr{border-bottom:1px solid var(--line-soft)}
  body.tktbl-bordered .rtable{border:1px solid var(--line);border-radius:12px;border-collapse:separate;border-spacing:0;overflow:hidden}
  body.tktbl-bordered .rtable td,body.tktbl-bordered .rtable th{border-bottom:1px solid var(--line);border-right:1px solid var(--line-soft)}
  body.tktbl-bordered .rtable td:last-child,body.tktbl-bordered .rtable th:last-child{border-right:none}
  body.tktbl-bordered .rtable tbody tr:last-child td{border-bottom:none}
  body.tktbl-clean .rtable tbody tr{border-bottom:none}
  body.tktbl-clean .rtable thead th{border-bottom:1px solid var(--line)}
  /* card-rows — each table row becomes a floating card with rounded corners and a gap. */
  body.tktbl-card-rows .rtable{border-collapse:separate;border-spacing:0 8px}
  body.tktbl-card-rows .rtable tbody tr{background:var(--card);box-shadow:var(--tk-shadow,var(--shadow-sm))}
  body.tktbl-card-rows .rtable tbody td{border-top:1px solid var(--line-soft);border-bottom:1px solid var(--line-soft)}
  body.tktbl-card-rows .rtable tbody td:first-child{border-left:1px solid var(--line-soft);border-radius:12px 0 0 12px}
  body.tktbl-card-rows .rtable tbody td:last-child{border-right:1px solid var(--line-soft);border-radius:0 12px 12px 0}
  body.tktbl-card-rows .rtable thead th{border:none}
  /* ─ DENSITY (4): airy | comfortable | compact | dense ─ */
  body.tkd-airy .px-tcard, body.tkd-airy .px-cozy-row{padding:28px}
  body.tkd-airy .rtable td, body.tkd-airy .rtable th{padding-top:16px;padding-bottom:16px}
  body.tkd-comfortable .px-tcard, body.tkd-comfortable .px-cozy-row{padding:20px}
  body.tkd-compact .px-tcard, body.tkd-compact .px-cozy-row{padding:14px 15px}
  body.tkd-compact .rtable td, body.tkd-compact .rtable th{padding-top:9px;padding-bottom:9px}
  body.tkd-dense .px-tcard, body.tkd-dense .px-cozy-row{padding:10px 12px}
  body.tkd-dense .rtable td, body.tkd-dense .rtable th{padding-top:6px;padding-bottom:6px}
  body.tkd-dense .px-line{padding-top:7px;padding-bottom:7px}
  /* ─ MOTION (6): none | subtle | smooth | springy | dramatic | reduced-only ─ */
  @keyframes tkFade{from{opacity:0}to{opacity:1}}
  @keyframes tkRise{from{opacity:0;transform:translateY(10px)}to{opacity:1;transform:none}}
  @keyframes tkSpring{0%{opacity:0;transform:scale(.92)}60%{opacity:1;transform:scale(1.02)}100%{transform:scale(1)}}
  @keyframes tkSlide{from{opacity:0;transform:translateY(18px)}to{opacity:1;transform:none}}
  body.tkm-subtle .px-tcard, body.tkm-subtle .px-cozy-row, body.tkm-subtle .kb-card, body.tkm-subtle tr[data-tkid], body.tkm-reduced-only .px-tcard, body.tkm-reduced-only .px-cozy-row, body.tkm-reduced-only .kb-card{animation:tkFade .35s var(--ease) both}
  body.tkm-smooth .px-tcard, body.tkm-smooth .px-cozy-row, body.tkm-smooth .kb-card, body.tkm-smooth tr[data-tkid]{animation:tkRise .4s var(--ease) both}
  body.tkm-springy .px-tcard, body.tkm-springy .px-cozy-row, body.tkm-springy .kb-card{animation:tkSpring .5s var(--ease) both}
  body.tkm-dramatic .px-tcard, body.tkm-dramatic .px-cozy-row, body.tkm-dramatic .kb-card{animation:tkSlide .45s var(--ease) both}
  body.tkm-dramatic .px-tcard:nth-child(2), body.tkm-dramatic .px-cozy-row:nth-child(2){animation-delay:.06s}
  body.tkm-dramatic .px-tcard:nth-child(3), body.tkm-dramatic .px-cozy-row:nth-child(3){animation-delay:.12s}
  body.tkm-dramatic .px-tcard:nth-child(4), body.tkm-dramatic .px-cozy-row:nth-child(4){animation-delay:.18s}
  @media(prefers-reduced-motion:reduce){body[class*=tkm-] .px-tcard, body[class*=tkm-] .px-cozy-row, body[class*=tkm-] .kb-card, body[class*=tkm-] tr[data-tkid]{animation:none}}
  /* ═══ EFFECTS PACK — glassmorphism intensity, hover effects, gradient accents ═══ */
  /* glass surfaces honor the adjustable blur + opacity tokens */
  body.tkc-glass .px-tcard, body.tkc-glass .kb-card, body.tkc-glass .px-cozy-row{background:color-mix(in srgb,var(--card) var(--tk-glass-a,72%),transparent);backdrop-filter:blur(var(--tk-blur,12px));-webkit-backdrop-filter:blur(var(--tk-blur,12px))}
  body.tklook .thread.bs-glass .bubble{backdrop-filter:blur(var(--tk-blur,12px));-webkit-backdrop-filter:blur(var(--tk-blur,12px))}
  /* adjustable card border width */
  body.tklook .px-tcard, body.tklook .kb-card, body.tklook .px-cozy-row{border-width:var(--tk-bw,1px)}
  /* card HOVER effects (7) */
  body.tkh-none .px-tcard:hover, body.tkh-none .kb-card:hover, body.tkh-none .px-cozy-row:hover{}
  body.tkh-lift .px-tcard, body.tkh-lift .kb-card, body.tkh-lift .px-cozy-row{transition:transform .18s var(--ease),box-shadow .18s var(--ease)}
  body.tkh-lift .px-tcard:hover, body.tkh-lift .kb-card:hover, body.tkh-lift .px-cozy-row:hover{transform:translateY(-4px);box-shadow:var(--shadow-lg)}
  body.tkh-glow .px-tcard, body.tkh-glow .kb-card, body.tkh-glow .px-cozy-row{transition:box-shadow .2s var(--ease),border-color .2s var(--ease)}
  body.tkh-glow .px-tcard:hover, body.tkh-glow .kb-card:hover, body.tkh-glow .px-cozy-row:hover{box-shadow:0 0 0 1px color-mix(in srgb,var(--accent) 40%,transparent),0 10px 30px -6px color-mix(in srgb,var(--accent) 45%,transparent);border-color:color-mix(in srgb,var(--accent) 40%,var(--line))}
  body.tkh-scale .px-tcard, body.tkh-scale .kb-card, body.tkh-scale .px-cozy-row{transition:transform .18s var(--ease)}
  body.tkh-scale .px-tcard:hover, body.tkh-scale .kb-card:hover, body.tkh-scale .px-cozy-row:hover{transform:scale(1.02)}
  body.tkh-tilt .px-tcard, body.tkh-tilt .kb-card{transition:transform .2s var(--ease),box-shadow .2s var(--ease)}
  body.tkh-tilt .px-tcard:hover, body.tkh-tilt .kb-card:hover{transform:perspective(700px) rotateX(3deg) translateY(-3px);box-shadow:var(--shadow-lg)}
  body.tkh-border .px-tcard, body.tkh-border .kb-card, body.tkh-border .px-cozy-row{transition:border-color .16s var(--ease)}
  body.tkh-border .px-tcard:hover, body.tkh-border .kb-card:hover, body.tkh-border .px-cozy-row:hover{border-color:var(--accent)}
  body.tkh-float .px-tcard, body.tkh-float .kb-card, body.tkh-float .px-cozy-row{transition:transform .22s var(--ease),box-shadow .22s var(--ease)}
  body.tkh-float .px-tcard:hover, body.tkh-float .kb-card:hover, body.tkh-float .px-cozy-row:hover{transform:translateY(-6px) scale(1.01);box-shadow:0 24px 50px -16px rgba(15,23,42,.35)}
  /* list-ROW hover (table/lines/cozy) */
  body.tkrh-tint tr[data-tkid]:hover, body.tkrh-tint .px-line:hover{background:color-mix(in srgb,var(--accent) 6%,transparent)}
  body.tkrh-accent-bar tr[data-tkid]:hover .rt-subcell{box-shadow:inset 3px 0 0 var(--accent)}
  body.tkrh-accent-bar .px-line:hover{box-shadow:inset 3px 0 0 var(--accent)}
  body.tkrh-lift .px-line{transition:transform .14s var(--ease)}body.tkrh-lift .px-line:hover{transform:translateX(3px)}
  body.tkrh-scale .px-line:hover{transform:scale(1.005)}
  /* GRADIENT accents — pills/turn/priority use the accent gradient */
  body.tkfx-grad .px-turn{background:var(--accent-bg,linear-gradient(135deg,var(--accent),var(--accent-d)))}
  body.tkfx-grad.tkp-solid .pill,body.tkfx-grad.tkp-badge .pill{background:linear-gradient(135deg,var(--pc),color-mix(in srgb,var(--pc) 60%,#000))}
  /* focus ring toggle */
  /* PHASE_PORTAL_P23 — ⚠ `:focus:not(:focus-visible)` IS LOAD-BEARING, DO NOT SIMPLIFY IT
     BACK TO `:focus`.
     tickets.ring_focus is an operator toggle whose own copy reads "An accessible outline on
     inputs and buttons WHEN NAVIGATING BY KEYBOARD" — but turning it off used to strip the
     ring from EVERY focus, keyboard included. That let an operator configure the portal into
     a WCAG 2.4.7 (Focus Visible, AA) failure from a switch labelled "Effects", which is
     precisely what P23 forbids ("operator can't configure below AA").
     Narrowing to :not(:focus-visible) keeps what the operator actually wanted — no ring when
     they CLICK a field — while a keyboard user always keeps theirs. The control still does a
     visible job, so nothing was retired to satisfy the rule. */
  body.tkfx-noring :is(#pg-requests,#pg-request,#pg-new,#pg-depts) :is(input,textarea,select,.btn):focus:not(:focus-visible){box-shadow:none!important;outline:none!important}
  /* ═══ PHASE_PORTAL_W11 — COMPOSE SURFACE: label_style / editor_height /
     suggest_pos. These keys existed in the design engine and were shipped in the
     bundle, but nothing read them, so the operator saw no change. Each one now
     drives a class or a variable, in the same namespaced pattern as the look pack. */
  /* .fld = a label+control pair, normalised by pxWrapFields() so the label can be
     repositioned without touching the page markup. */
  #pg-new .fld,#pg-status .fld{position:relative}
  /* ─ LABEL STYLE (5): over | floating | inline | placeholder-only | side ─ */
  /* over = the default; the base stylesheet already stacks label above control. */
  /* floating — label rides inside the field and shrinks up on focus/fill (Zendesk/
     Material pattern). Applied to inputs and selects only: floating a label over a
     rich-text toolbar looks broken, so the message box keeps its label above. */
  body.tkl-floating #pg-new .fld:has(>input:not([type=file])),body.tkl-floating #pg-new .fld:has(>select){padding-top:0}
  body.tkl-floating #pg-new .fld:has(>input:not([type=file]))>label,body.tkl-floating #pg-new .fld:has(>select)>label{position:absolute;left:13px;top:50%;transform:translateY(-50%);margin:0;padding:0 3px;background:transparent;pointer-events:none;text-transform:none;letter-spacing:0;font-size:13.5px;font-weight:600;color:var(--ink-3);transition:top .16s var(--ease),font-size .16s var(--ease),color .16s var(--ease),transform .16s var(--ease)}
  body.tkl-floating #pg-new .fld:has(>input:not([type=file]))>input,body.tkl-floating #pg-new .fld:has(>select)>select{padding-top:19px;padding-bottom:7px}
  body.tkl-floating #pg-new .fld:has(>input:focus)>label,body.tkl-floating #pg-new .fld:has(>input:not(:placeholder-shown))>label,body.tkl-floating #pg-new .fld:has(>select)>label{top:7px;transform:none;font-size:10.5px;font-weight:800;letter-spacing:.05em;text-transform:uppercase;color:var(--accent)}
  body.tkl-floating #pg-new .fld>input::placeholder{opacity:0;transition:opacity .16s var(--ease)}
  body.tkl-floating #pg-new .fld>input:focus::placeholder{opacity:.55}
  /* inline — label in a left column, control on the right (Jira/ServiceNow forms) */
  body.tkl-inline #pg-new .fld{display:grid;grid-template-columns:148px minmax(0,1fr);gap:12px;align-items:center}
  body.tkl-inline #pg-new .fld>label{margin:0;text-align:right}
  /* side — same idea, wider label column, top-aligned so it reads well next to a textarea */
  body.tkl-side #pg-new .fld{display:grid;grid-template-columns:190px minmax(0,1fr);gap:14px;align-items:start}
  body.tkl-side #pg-new .fld>label{margin:0;padding-top:11px;text-align:right}
  @media(max-width:640px){body.tkl-inline #pg-new .fld,body.tkl-side #pg-new .fld{grid-template-columns:1fr;gap:0}body.tkl-inline #pg-new .fld>label,body.tkl-side #pg-new .fld>label{text-align:left;padding-top:0;margin:14px 0 6px}}
  /* placeholder-only — the field's placeholder carries the label. The <label> stays in
     the DOM for screen readers, it is only hidden visually. */
  body.tkl-placeholder-only #pg-new .fld>label{position:absolute;width:1px;height:1px;padding:0;margin:0;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0}
  /* ─ EDITOR HEIGHT — operator-set compose box height ─ */
  body.tklook #pg-new #p-message{min-height:var(--tk-editor-h,130px)}
  /* ─ PHASE_PORTAL_W16 — COMPOSE WIDTH: cap the compose card so the form can be made
     narrower for comfortable reading or left full-width. 'full' = no cap = previous behaviour. */
  body.cw-comfortable #p-panel-new{max-width:560px}
  body.cw-normal #p-panel-new{max-width:720px}
  body.cw-wide #p-panel-new{max-width:900px}
  body.cw-full #p-panel-new{max-width:none}
  /* ─ SUGGEST POSITION (4): sidebar | inline | modal | off ─ */
  /* inline — the answers card drops into the main column under the subject field. */
  #p-suggest-card.sg-pos-inline{position:static;margin:0 0 4px;padding:15px 16px}
  /* modal — a dismissible floating panel, so a long form is not pushed around. It only
     shows itself once there is something to say (pxSuggest adds .sg-has). */
  #p-suggest-card.sg-pos-modal{position:fixed;right:20px;bottom:20px;z-index:60;width:330px;max-width:calc(100vw - 40px);max-height:60vh;overflow:auto;box-shadow:var(--shadow-lg,0 24px 50px -16px rgba(15,23,42,.35));display:none}
  #p-suggest-card.sg-pos-modal.sg-has{display:block;animation:tkRise .28s var(--ease) both}
  #p-suggest-card.sg-pos-modal .sg-close{position:absolute;top:9px;right:10px;border:none;background:none;cursor:pointer;color:var(--ink-3);font-size:17px;line-height:1;padding:3px 5px;border-radius:7px}
  #p-suggest-card.sg-pos-modal .sg-close:hover{background:var(--line-soft);color:var(--ink)}
  @media(max-width:640px){#p-suggest-card.sg-pos-modal{left:12px;right:12px;width:auto;bottom:12px}}
  /* ─ AFTER SUBMIT — the KB block on the success card (after_submit = success-kb) ─ */
  #p-success-kb{margin-top:18px;text-align:left;border-top:1px solid var(--line);padding-top:16px}
  #p-success-kb .sk-h{font-size:12.5px;font-weight:800;color:var(--ink-2);margin-bottom:9px}
  #p-success-kb .sg-item{display:block}
  /* ─ AFTER SUBMIT — custom-message body ─ */
  #p-success-custom{margin-top:6px;color:var(--ink-2);font-size:14px;line-height:1.6}
  /* ═══ PHASE_PORTAL_W12 — START VIEWS: landing / landing-split / wizard / search-first /
     channel-hub. Built on the existing .dp-* card system so they inherit every look control
     (card style, radius, shadow, density, hover) instead of forking a second visual system. */
  .px-start-sep{display:flex;align-items:center;gap:12px;margin:22px 0 16px;color:var(--ink-3);font-size:12px;font-weight:800;text-transform:uppercase;letter-spacing:.07em}
  .px-start-sep::before,.px-start-sep::after{content:"";flex:1;height:1px;background:var(--line)}
  /* landing-split — answer on the left, ask on the right */
  .px-split{display:grid;grid-template-columns:1fr 1fr;gap:16px;align-items:start}
  .px-split-col{padding:20px}
  .px-split-h{font-size:14px;font-weight:800;color:var(--ink);margin-bottom:13px}
  @media(max-width:860px){.px-split{grid-template-columns:1fr}}
  /* search-first — the deflection gate */
  .px-sf{padding:22px}
  .px-sf-search{margin:0 0 14px}
  .px-sf-big{padding:13px 16px}
  .px-sf-big input{font-size:15px}
  .px-sf-foot{display:flex;align-items:center;gap:12px;flex-wrap:wrap;margin-top:16px;padding-top:15px;border-top:1px solid var(--line);color:var(--ink-3);font-size:13.5px}
  .px-sf-foot .btn{margin-top:0;width:auto;padding:10px 18px}
  #px-sf-res .sg-empty{padding:10px 2px}
  /* wizard — two honest steps */
  .px-wz-steps{display:flex;align-items:center;gap:10px;margin-bottom:18px;flex-wrap:wrap}
  .px-wz-step{display:flex;align-items:center;gap:8px;font-size:13px;font-weight:700;color:var(--ink-3)}
  .px-wz-step b{width:24px;height:24px;border-radius:50%;display:flex;align-items:center;justify-content:center;background:var(--line-soft,color-mix(in srgb,var(--ink) 8%,transparent));color:var(--ink-2);font-size:12px}
  .px-wz-step.on{color:var(--ink)}
  .px-wz-step.on b{background:var(--accent-bg,var(--accent));color:#fff}
  .px-wz-line{flex:1;min-width:20px;height:1px;background:var(--line)}
  /* a dp-card rendered as a link (help center) must not look different from the buttons */
  a.dp-card{text-decoration:none}
  /* ═══ PHASE_PORTAL_W13 — ICON SET ═══
     SVG icons take the accent; emoji carry their own colour and need no tint. */
  .px-ic,.sd-head .px-ic{display:inline-flex;align-items:center;justify-content:center;color:var(--accent);flex:none}
  .sd-head .px-ic{margin-right:2px}
  .px-ic-s{display:block}
  .dp-ic .px-ic-s{color:var(--accent)}
  /* the department tile keeps one footprint whichever set is chosen, so switching sets does
     not reflow the picker */
  .dp-ic{display:inline-flex;align-items:center;justify-content:center}
  body.tki-emoji .dp-ic .px-ic-e{filter:none}
  /* toolbar + request table */
  .rq-toolbar{display:flex;align-items:center;gap:12px;flex-wrap:wrap;margin-bottom:12px}
  .rq-search{flex:1;min-width:220px;display:flex;align-items:center;gap:9px;background:var(--card);border:1px solid var(--line);border-radius:11px;padding:9px 13px;color:var(--ink-3)}
  .rq-search input{border:none;padding:0;box-shadow:none;font-size:13.5px;background:transparent}
  .rq-search input:focus{box-shadow:none;border:none}
  .rq-search:focus-within{border-color:var(--accent);box-shadow:0 0 0 3px color-mix(in srgb,var(--accent) 11%,transparent)}
  .rtable-wrap{overflow-x:auto}
  .px-listcap{display:flex;align-items:center;gap:10px;margin-top:14px;padding:12px 16px;border-radius:12px;
    background:color-mix(in srgb,var(--accent) 7%,var(--card));border:1px solid color-mix(in srgb,var(--accent) 22%,var(--line));
    font-size:13px;color:var(--ink-2)}
  .px-listcap-i{flex:none;width:20px;height:20px;border-radius:50%;display:flex;align-items:center;justify-content:center;
    background:var(--accent-bg,var(--accent));color:#fff;font-size:12px;font-weight:800}
  .rtable{width:100%;border-collapse:collapse;font-size:13.5px}
  /* P13 — the table must never exceed its own card. Every cell was nowrap, so a
     long subject plus a two-pill status cell pushed the table's min-content past
     the container and left a stray horizontal scrollbar on a table that looked
     like it fitted. The subject now truncates (max-width:0 is the standard trick
     that lets an auto-layout column shrink) and a multi-pill status cell wraps. */
  .rtable .rt-subcell{max-width:0;width:46%}
  .rtable .rt-subcell .rt-sub{display:block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  /* the CELL wraps so two pills stack, but each PILL stays on one line — letting
     the pill itself wrap broke "Awaiting Your Reply" across two lines and made
     that row twice the height of its neighbours. */
  .rtable td:has(.px-turn){white-space:normal}
  .rtable td:has(.px-turn) .pill,.rtable td:has(.px-turn) .px-turn{white-space:nowrap}
  .rtable td:has(.px-turn) .pill{margin-top:3px}
  .rtable th{text-align:left;font-size:11px;font-weight:800;text-transform:uppercase;letter-spacing:.06em;color:var(--ink-3);padding:12px 16px;border-bottom:1px solid var(--line)}
  .rtable td{padding:13px 16px;border-bottom:1px solid var(--line-soft);color:var(--ink-2);white-space:nowrap}
  .rtable td.rt-sub{white-space:normal;font-weight:700;color:var(--ink);max-width:380px}
  .rtable tbody tr{cursor:pointer;transition:background .13s var(--ease)}
  .rtable tbody tr:hover{background:color-mix(in srgb,var(--accent) 4%,transparent)}
  .rtable tbody tr:hover .rt-sub{color:var(--accent)}
  .rtable tbody tr:last-child td{border-bottom:none}
  .rtable-wrap.card{padding:0}
  /* PHASE_PORTAL_COLCUST — customer-reorderable + resizable columns */
  .rtable.rt-cust th.rt-th{position:relative;cursor:grab;user-select:none}
  .rtable.rt-cust th.rt-th:active{cursor:grabbing}
  .rtable.rt-cust th.rt-thdrag{opacity:.5;background:color-mix(in srgb,var(--accent) 8%,transparent)}
  .rtable.rt-cust th .rt-cresize{position:absolute;top:0;right:0;width:9px;height:100%;cursor:col-resize;z-index:2}
  .rtable.rt-cust th .rt-cresize::after{content:"";position:absolute;top:22%;right:3px;height:56%;width:2px;border-radius:2px;background:transparent;transition:background .12s var(--ease)}
  .rtable.rt-cust th:hover .rt-cresize::after{background:color-mix(in srgb,var(--accent) 40%,transparent)}
  .rtable.rt-resizing{cursor:col-resize;user-select:none}
  .rt-subcell .rt-sub{font-weight:700;color:var(--ink)}
  .rt-cat{font-size:11.5px;font-weight:700;background:color-mix(in srgb,var(--accent) 10%,var(--line-soft));color:var(--accent);padding:2px 8px;border-radius:7px}
  .unread-dot{display:inline-block;width:7px;height:7px;border-radius:50%;background:var(--accent);margin-right:7px;vertical-align:middle}
  .prio-tag{display:inline-flex;align-items:center;gap:6px;font-size:12px;font-weight:700;color:var(--ink-2)}
  /* ═══ W3 — 10 list layouts ═══ */
  #px-list-host{margin-top:2px}
  .px-list-bulk{display:flex;align-items:center;gap:9px;flex-wrap:wrap;margin:10px 0;padding:9px 11px;border:1px solid var(--line);border-radius:12px;background:color-mix(in srgb,var(--accent) 4%,var(--card))}
  .px-list-bulk.hidden{display:none}.px-list-bulk-count{font-size:12px;font-weight:800;color:var(--ink-2);margin-right:auto}
  .px-list-bulk button{border:1px solid var(--line);background:var(--card);color:var(--ink-2);border-radius:8px;padding:6px 9px;font:inherit;font-size:11.5px;font-weight:750;cursor:pointer}
  .px-list-bulk button:hover:not(:disabled){border-color:var(--accent);color:var(--accent)}.px-list-bulk button:disabled{opacity:.45;cursor:not-allowed}
  .px-bulk-check{display:inline-flex;align-items:center;justify-content:center;width:22px;height:22px;flex:none;border:1px solid var(--line);border-radius:7px;background:var(--card);color:transparent;cursor:pointer;vertical-align:middle}
  .px-bulk-check::after{content:"✓";font-size:12px;font-weight:900}.px-bulk-check[aria-checked="true"]{background:var(--accent);border-color:var(--accent);color:#fff}
  .px-bulk-cell{width:44px!important;padding-right:4px!important}.px-bulk-head{width:44px!important;padding-right:4px!important}
  .px-bulk-row:not(tr){position:relative}.px-bulk-row:not(tr)>.px-bulk-check{margin-right:8px}
  .px-bulk-selected{box-shadow:inset 3px 0 0 var(--accent)!important;background:color-mix(in srgb,var(--accent) 6%,var(--card))!important}
  .px-list-avatar{display:inline-flex;align-items:center;justify-content:center;width:24px;height:24px;margin-right:8px;border-radius:8px;background:color-mix(in srgb,var(--accent) 12%,var(--line-soft));color:var(--accent);font-size:9px;font-weight:900;vertical-align:middle;letter-spacing:.02em}
  .px-list-avatar.status{width:12px;height:12px;border-radius:50%;background:var(--la-color,var(--accent));color:transparent;margin-right:9px}
  .px-row-open{margin-left:auto;border:0;background:transparent;color:var(--accent);font:inherit;font-size:11.5px;font-weight:800;cursor:pointer;padding:5px 7px;border-radius:7px;white-space:nowrap}
  .px-row-open:hover{background:color-mix(in srgb,var(--accent) 10%,transparent)}.rtable .px-row-open{margin-left:10px}
  @media(max-width:560px){.px-list-bulk-count{width:100%;margin:0}.px-list-bulk button{flex:1}}
  .tl-table-dense .rtable td{padding:8px 14px}.tl-table-dense .rtable th{padding:8px 14px}
  /* compact / minimal-lines */
  .px-lines .px-line{display:flex;align-items:center;gap:12px;padding:11px 16px;border-bottom:1px solid var(--line-soft);cursor:pointer;transition:background .12s var(--ease)}
  .px-lines .px-line:last-child{border-bottom:none}
  .px-lines .px-line:hover{background:color-mix(in srgb,var(--accent) 4%,transparent)}
  .px-lines .rt-sub{flex:1;font-weight:700;color:var(--ink);min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  .px-lines .px-line:hover .rt-sub{color:var(--accent)}
  .px-line-meta{font-size:12px;color:var(--ink-3);white-space:nowrap}
  /* PHASE_PORTAL_P21 — the request-list row broke on every phone.
     .px-line is a nowrap flex row: .rt-sub shrinks fine (flex:1 + min-width:0 + ellipsis)
     but the status pill and the meta are rigid, so below ~425px the row could not fit and
     the pill rendered 132px OUTSIDE its own parent, scrolling the whole document sideways.
     This list had no mobile rule at all. Wrapping is the right answer rather than shrinking
     the pill: a status is not something to truncate. Scoped to --bp-xs because 480px and up
     measured clean, so larger screens keep the single-line row. */
  @media(max-width:480px){
    .px-lines .px-line{flex-wrap:wrap;row-gap:6px}
    .px-lines .rt-sub{flex:1 0 100%}
  }
  .tl-minimal-lines.px-lines,.tl-minimal-lines .px-lines{border:none;box-shadow:none;background:transparent}
  .tl-minimal-lines .px-line{border-color:var(--line-soft)}
  /* cozy */
  .px-cozy{display:flex;flex-direction:column;gap:10px}
  .px-cozy-row{display:flex;align-items:center;justify-content:space-between;gap:14px;padding:15px 18px;cursor:pointer;transition:transform .16s var(--ease),box-shadow .16s var(--ease),border-color .16s var(--ease)}
  .px-cozy-row:hover{transform:translateY(-2px);box-shadow:var(--shadow-md);border-color:color-mix(in srgb,var(--accent) 30%,var(--line))}
  .cz-sub{font-weight:750;font-size:14.5px;color:var(--ink)}.px-cozy-row:hover .cz-sub{color:var(--accent)}
  .cz-meta{font-size:12px;color:var(--ink-3);margin-top:3px}
  .cz-right{display:flex;align-items:center;gap:8px;flex-shrink:0}
  /* ADDITIVE_PORTAL_PREMIUM_2026 — Service Desk list. */
  .px-service-desk{display:flex;flex-direction:column;gap:14px}.psd-summary{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:10px}.psd-stat{padding:14px 16px;border:1px solid var(--line);border-radius:14px;background:linear-gradient(145deg,color-mix(in srgb,var(--accent) 4%,var(--card)),var(--card));box-shadow:0 12px 34px -30px rgba(15,23,42,.5)}.psd-stat span{display:block;font-size:10.5px;text-transform:uppercase;letter-spacing:.08em;color:var(--ink-3);font-weight:850}.psd-stat b{display:block;margin-top:5px;font-size:23px;line-height:1;color:var(--ink)}
  .psd-queue{display:flex;flex-direction:column;border:1px solid var(--line);border-radius:18px;overflow:hidden;background:var(--card);box-shadow:0 22px 55px -48px rgba(15,23,42,.65)}.psd-row{display:grid;grid-template-columns:minmax(0,1fr) auto;gap:18px;align-items:center;padding:16px 18px;border-bottom:1px solid var(--line-soft);cursor:pointer;transition:background .15s var(--ease),transform .15s var(--ease),box-shadow .15s var(--ease);position:relative}.psd-row:last-child{border-bottom:0}.psd-row:hover{background:color-mix(in srgb,var(--accent) 4%,var(--card));box-shadow:inset 4px 0 0 color-mix(in srgb,var(--accent) 72%,transparent)}.psd-main{min-width:0}.psd-kicker{display:flex;align-items:center;gap:8px;flex-wrap:wrap;margin-bottom:6px}.psd-id{font-size:11px;font-weight:850;color:var(--ink-3)}.psd-dept,.psd-topic{font-size:10.5px;font-weight:800;padding:3px 8px;border-radius:999px;background:var(--line-soft);color:var(--ink-2)}.psd-topic{color:var(--accent);background:color-mix(in srgb,var(--accent) 10%,transparent)}.psd-sub{font-size:14.5px;font-weight:780;color:var(--ink);line-height:1.35}.psd-row:hover .psd-sub{color:var(--accent)}.psd-meta{display:flex;gap:13px;flex-wrap:wrap;margin-top:6px;font-size:11.5px;color:var(--ink-3)}.psd-state{display:flex;align-items:center;justify-content:flex-end;gap:8px;flex-wrap:wrap;max-width:260px}
  /* ADDITIVE_PORTAL_PREMIUM_2026 — Account Care list. */
  .px-account-care{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:14px}.pac-card{display:grid;grid-template-columns:5px minmax(0,1fr) auto;gap:16px;align-items:stretch;min-height:154px;padding:0 18px 0 0;border:1px solid var(--line);border-radius:18px;background:linear-gradient(150deg,color-mix(in srgb,var(--accent) 4%,var(--card)),var(--card));box-shadow:0 18px 46px -40px rgba(15,23,42,.62);overflow:hidden;cursor:pointer;transition:transform .16s var(--ease),box-shadow .16s var(--ease),border-color .16s var(--ease)}.pac-card:hover{transform:translateY(-3px);box-shadow:0 24px 54px -38px rgba(15,23,42,.62);border-color:color-mix(in srgb,var(--accent) 30%,var(--line))}.pac-rail{background:linear-gradient(180deg,var(--accent),color-mix(in srgb,var(--accent) 20%,transparent))}.pac-content{padding:17px 0;min-width:0}.pac-top{display:flex;align-items:center;justify-content:space-between;gap:10px;margin-bottom:9px}.pac-context{font-size:10.5px;font-weight:850;text-transform:uppercase;letter-spacing:.065em;color:var(--accent)}.pac-id{font-size:11px;font-weight:800;color:var(--ink-3);white-space:nowrap}.pac-sub{font-size:15px;font-weight:780;line-height:1.35;color:var(--ink)}.pac-card:hover .pac-sub{color:var(--accent)}.pac-details{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:10px;margin-top:14px}.pac-details span{min-width:0;font-size:11.5px;color:var(--ink-2);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.pac-details b{display:block;margin-bottom:2px;font-size:9.5px;text-transform:uppercase;letter-spacing:.06em;color:var(--ink-3)}.pac-state{align-self:center;display:flex;flex-direction:column;align-items:flex-end;gap:7px;padding:14px 0;min-width:122px}
  @media(max-width:860px){.psd-summary{grid-template-columns:repeat(2,minmax(0,1fr))}.px-account-care{grid-template-columns:1fr}}
  @media(max-width:640px){.psd-row{grid-template-columns:1fr}.psd-state{justify-content:flex-start;max-width:none}.psd-meta{gap:7px 12px}.pac-card{grid-template-columns:4px minmax(0,1fr);padding-right:14px}.pac-state{grid-column:2;flex-direction:row;align-items:center;flex-wrap:wrap;justify-content:flex-start;padding:0 0 15px}.pac-details{grid-template-columns:1fr 1fr}.pac-details span:last-child{grid-column:1/-1}.psd-summary{gap:8px}.psd-stat{padding:12px 13px}.psd-stat b{font-size:20px}}
  /* cards */
  .px-cards{display:grid;gap:14px}.px-cards.cards-3{grid-template-columns:repeat(auto-fill,minmax(260px,1fr))}.px-cards.cards-2{grid-template-columns:repeat(2,minmax(0,1fr))}
  @media(max-width:640px){.px-cards.cards-2{grid-template-columns:1fr}}
  .px-tcard{padding:16px 18px;cursor:pointer;display:flex;flex-direction:column;gap:10px;transition:transform .16s var(--ease),box-shadow .16s var(--ease),border-color .16s var(--ease)}
  .px-tcard:hover{transform:translateY(-3px);box-shadow:var(--shadow-md);border-color:color-mix(in srgb,var(--accent) 30%,var(--line))}
  /* P06 — badges and the id share one row without ever colliding: pills keep to
     one line, the id right-aligns and, when space runs out, the row wraps. */
  /* P13 — the id is PINNED top-right instead of being a flex sibling. As a
     sibling it competed for the first line: a card with two status pills
     (90 + 145px) pushed DEMO-1042 onto a second row, so that card's header was
     54px against 27px for its neighbours and the grid read ragged. Pinned, the
     pills wrap among themselves and the id is always in the same place. */
  .tc-top{display:flex;align-items:center;gap:8px;row-gap:6px;flex-wrap:wrap;position:relative;padding-right:78px;min-height:26px}
  .tc-top .pill,.tc-top .px-turn{white-space:nowrap}
  .tc-id{font-size:12px;color:var(--ink-3);font-weight:700;white-space:nowrap;position:absolute;right:0;top:3px}
  .tc-sub{font-weight:750;font-size:14.5px;color:var(--ink);line-height:1.35}.px-tcard:hover .tc-sub{color:var(--accent)}
  .tc-foot{display:flex;align-items:center;justify-content:space-between;font-size:12px;color:var(--ink-3);margin-top:auto}
  .tc-agent{font-weight:700}
  /* timeline */
  /* padding-left:6px pushed the timeline's cards 6px right of the toolbar and every other
     layout — measured 361 vs 355. Nothing used the inset (no rail is drawn from it), so it was
     just an unexplained offset. Removed so timeline aligns with the search bar above it. */
  .px-timeline{position:relative}
  .tl-month{font-size:12px;font-weight:800;text-transform:uppercase;letter-spacing:.06em;color:var(--ink-3);margin:18px 0 10px}
  .tl-item{display:flex;align-items:center;gap:12px;padding:11px 14px;background:var(--card);border:1px solid var(--line-soft);border-radius:12px;margin-bottom:8px;cursor:pointer;position:relative;transition:border-color .14s var(--ease)}
  .tl-item:hover{border-color:color-mix(in srgb,var(--accent) 30%,var(--line))}
  .tl-dot{width:10px;height:10px;border-radius:50%;background:var(--ink-3);flex-shrink:0}
  /* FALLBACK ONLY — the renderer now sets the dot's colour inline from pxStatusColor so the
     operator's status_map applies. These remain for the case where that returns nothing.
     `answered` is deliberately NOT grouped with closed/resolved: it means the agent has replied
     and the CUSTOMER now owes a response, which is an active state, not a finished one. */
  .tl-dot.closed,.tl-dot.resolved{background:var(--ok)}
  .tl-dot.answered{background:#10b981}
  .tl-dot.customer_reply,.tl-dot.open{background:var(--accent)}
  .tl-dot.in_progress{background:#3b82f6}
  .tl-dot.pending,.tl-dot.on_hold{background:#f59e0b}
  /* A month carried over from the previous page, so "June 2026" does not look like it began twice. */
  .tl-month-cont{
    margin-left:8px;padding:2px 7px;border-radius:999px;
    font-size:9.5px;font-weight:700;letter-spacing:.06em;text-transform:uppercase;
    color:var(--ink-3,#64748b);background:color-mix(in srgb,var(--ink-3,#94a3b8) 14%,transparent);
    vertical-align:middle;
  }
  .tl-body{flex:1;min-width:0}.tl-body .rt-sub{font-weight:700;color:var(--ink)}.tl-item:hover .rt-sub{color:var(--accent)}.tl-meta{font-size:11.5px;color:var(--ink-3);margin-top:1px}
  /* kanban */
  /* ⚠ The board CAPS its own height and each lane scrolls on its own.
     Without this a grid lane stretches to the tallest row, so an account with 28 solved
     and 0 open rendered three EMPTY grey slabs 2,243px tall — pages of nothing to scroll
     past. Capping the lane and scrolling .kb-cards keeps the board one screen whatever the
     distribution, which is what makes a kanban readable in the first place. */
  .px-kanban{display:grid;grid-template-columns:repeat(var(--kb-cols,4),minmax(0,1fr));gap:12px;align-items:stretch}
  @media(max-width:860px){.px-kanban{grid-template-columns:repeat(min(var(--kb-cols,4),2),1fr)}}@media(max-width:560px){.px-kanban{grid-template-columns:1fr}}
  .kb-lane{background:var(--line-soft);border-radius:14px;padding:12px;min-height:120px;max-height:min(68vh,620px);display:flex;flex-direction:column}
  .kb-head{font-size:12px;font-weight:800;color:var(--ink-2);margin-bottom:10px;display:flex;align-items:center;gap:8px}
  .kb-count{background:var(--card);border-radius:999px;padding:1px 8px;font-size:11px;color:var(--ink-3)}
  .kb-cards{display:flex;flex-direction:column;gap:8px;overflow-y:auto;min-height:0;overscroll-behavior:contain;padding-right:3px}
  /* standard pair fenced to Firefox — set here it would win in Chrome 121+ and replace the 8px
     pill below with Chrome's own 'thin' bar (arrow buttons on Windows). */
  @supports not selector(::-webkit-scrollbar){.kb-cards{scrollbar-width:thin}}
  .kb-cards::-webkit-scrollbar{width:8px}
  .kb-cards::-webkit-scrollbar-thumb{background:color-mix(in srgb,var(--ink-3) 34%,transparent);border-radius:999px}
  .kb-cards::-webkit-scrollbar-track{background:transparent}
  .kb-head{flex:0 0 auto}
  .kb-card{background:var(--card);border:1px solid var(--line);border-radius:11px;padding:11px 12px;cursor:pointer;transition:transform .14s var(--ease),box-shadow .14s var(--ease)}
  .kb-card:hover{transform:translateY(-2px);box-shadow:var(--shadow-sm)}
  .kb-sub{font-weight:700;font-size:13px;color:var(--ink);line-height:1.35}.kb-meta{font-size:11px;color:var(--ink-3);margin-top:5px}
  .kb-empty{font-size:12px;color:var(--ink-3);text-align:center;padding:12px;margin:auto 0;flex:1;display:flex;align-items:center;justify-content:center}
  /* split */
  .px-split{display:grid;grid-template-columns:320px minmax(0,1fr);gap:14px;align-items:start}
  @media(max-width:860px){.px-split{grid-template-columns:1fr}.sp-preview{display:none}}
  /* PHASE_PORTAL_SPLIT_SCROLL — the list column FREE-FITS to its grid row.
     It had a hardcoded 70vh cap, then briefly a viewport cap; both were wrong. A viewport cap
     still dictates a height of its own, so a short conversation left the column running past
     the content and a long one still clipped early.
     Instead the two columns share the row: the grid stretches them, the preview beside it sets
     the row height, and the list scrolls INSIDE that. So the list can never make the page taller
     than the preview already does, and it only scrolls when the content beside it is shorter
     than the list — which is exactly when a scroll is warranted.
     min-height:0 is load-bearing: a grid item defaults to min-content, so without it the item
     refuses to shrink and overflow-y never engages. */
  .px-split{align-items:stretch}
  /* The WRAPPER is the grid item and it is deliberately height-less: min-height:0 stops the
     grid's default min-content floor, so the row is sized by the PREVIEW alone. */
  .sp-listwrap{position:relative;min-height:0}
  /* Absolutely positioned, so however many rows there are they contribute NOTHING to the row
     height. The list simply fills whatever the preview established, and scrolls if that is
     smaller than its content. */
  .sp-list{
    position:absolute;inset:0;
    padding:0;margin:0;
    overflow-y:auto;
    overscroll-behavior:contain;   /* reaching the end must not scroll the page behind it */
  }
  @media(max-width:860px){
    /* Stacked on a phone the preview is hidden, so there is no sibling to take height from —
       back to normal flow and let the page scroll. */
    .sp-listwrap{position:static}
    .sp-list{position:static;inset:auto;overflow-y:visible}
  }
  /* ── HIDDEN (default) ── the bar is gone; the column still scrolls by wheel, trackpad and
     keyboard. Firefox needs scrollbar-width, WebKit needs the pseudo-element at zero width. */
  body.spsb-hidden .sp-list{scrollbar-width:none;-ms-overflow-style:none}
  body.spsb-hidden .sp-list::-webkit-scrollbar{width:0;height:0}
  /* ── THIN ── 6px, transparent track, thumb only tints on hover. The standard pair is fenced to
     Firefox: Chrome 121+ prefers it over ::-webkit-scrollbar and would draw its own 'thin' bar
     (with the Windows arrow buttons) instead of the 6px one below. */
  @supports not selector(::-webkit-scrollbar){
    body.spsb-thin .sp-list{scrollbar-width:thin;
      scrollbar-color:color-mix(in srgb,var(--ink-3,#94a3b8) 45%,transparent) transparent}
  }
  body.spsb-thin .sp-list::-webkit-scrollbar{width:6px}
  body.spsb-thin .sp-list::-webkit-scrollbar-track{background:transparent}
  body.spsb-thin .sp-list::-webkit-scrollbar-thumb{background:color-mix(in srgb,var(--ink-3,#94a3b8) 32%,transparent);border-radius:999px}
  body.spsb-thin .sp-list:hover::-webkit-scrollbar-thumb{background:color-mix(in srgb,var(--ink-3,#94a3b8) 55%,transparent)}
  /* ── NATIVE ── nothing overridden, the browser default. */
  .sp-row{padding:13px 16px;border-bottom:1px solid var(--line-soft);cursor:pointer;transition:background .12s var(--ease)}
  .sp-row:hover{background:color-mix(in srgb,var(--accent) 4%,transparent)}.sp-row.on{background:color-mix(in srgb,var(--accent) 8%,transparent);box-shadow:inset 3px 0 0 var(--accent)}
  .sp-top{display:flex;align-items:center;justify-content:space-between;gap:7px;row-gap:5px;flex-wrap:wrap;margin-bottom:5px}
  .sp-top .pill,.sp-top .px-turn{white-space:nowrap}
  .sp-id{font-size:11.5px;color:var(--ink-3);font-weight:700;margin-left:auto;white-space:nowrap;flex:0 0 auto}
  .sp-sub{font-weight:700;font-size:13.5px;color:var(--ink);line-height:1.35}.sp-meta{font-size:11.5px;color:var(--ink-3);margin-top:3px}
  .sp-preview{padding:20px;min-height:300px;position:sticky;top:calc(var(--px-navh,0px) + 13px)}
  .sp-pv-head strong{font-size:16px}.sp-pv-meta{font-size:12px;color:var(--ink-3);margin-top:6px;display:flex;align-items:center;gap:8px}
  /* PHASE_PORTAL_SPLIT_REPLY — Reply pinned top-right inside the reading pane.
     The head becomes a row: title block grows, button stays put at its natural width. The title
     block gets min-width:0 so a long subject ellipsises instead of shoving the button off. */
  .sp-pv-head{display:flex;align-items:flex-start;justify-content:space-between;gap:12px}
  .sp-pv-headtx{min-width:0;flex:1}
  .sp-pv-reply{
    flex:none;display:inline-flex;align-items:center;gap:7px;
    padding:7px 13px;font:inherit;font-size:12.5px;font-weight:700;
    color:#fff;background:var(--accent);
    border:0;border-radius:999px;cursor:pointer;
    box-shadow:0 2px 8px -2px color-mix(in srgb,var(--accent) 55%,transparent);
    transition:background .14s var(--ease,ease),transform .14s var(--ease,ease);
  }
  .sp-pv-reply:hover{background:color-mix(in srgb,var(--accent) 88%,#000);transform:translateY(-1px)}
  .sp-pv-reply:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
  /* The three styles mirror the FAB's own vocabulary so the two never disagree:
     icon = glyph only, pill = glyph + word, extended = roomier with tracking. */
  .sp-pv-reply.spr-icon{padding:8px;border-radius:50%}
  .sp-pv-reply.spr-icon .sp-pv-reply-lbl{
    /* Hidden visually, kept for screen readers — an icon-only button still needs a name. */
    position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;
  }
  .sp-pv-reply.spr-extended{padding:9px 17px;font-size:13px;letter-spacing:.01em}
  @media(max-width:860px){
    /* Stacked: the pane is full width, so let the head wrap rather than crushing the title. */
    .sp-pv-head{flex-wrap:wrap}
    .sp-pv-reply{order:3}
  }
  .sp-pv-thread{margin-top:14px}
  /* pager */
  .px-pager{margin-top:16px;display:flex;justify-content:center}
  .pg-nums{display:flex;gap:4px}
  .pg-nums button{min-width:34px;height:34px;border:1px solid var(--line);background:var(--card);border-radius:9px;font-size:13px;font-weight:700;color:var(--ink-2);cursor:pointer;transition:.13s var(--ease)}
  .pg-nums button:hover:not(:disabled){border-color:var(--accent);color:var(--accent)}.pg-nums button.on{background:var(--accent);border-color:var(--accent);color:#fff}.pg-nums button:disabled{opacity:.4;cursor:default}
  .pg-more{margin:0}
  /* PHASE_PORTAL_VSCROLL — infinite-scroll sentinel */
  .pg-inf{display:flex;justify-content:center;padding:18px}
  .pg-inf-dots{display:flex;gap:6px}
  .pg-inf-dots i{width:8px;height:8px;border-radius:50%;background:var(--accent);opacity:.65;animation:skPulse 1s infinite}
  .pg-inf-dots i:nth-child(2){animation-delay:.15s}.pg-inf-dots i:nth-child(3){animation-delay:.3s}
  /* detail two-column */
  .rq-grid{display:grid;grid-template-columns:minmax(0,1fr) 280px;gap:18px;align-items:start}
  /* P14 — composable request-detail regions. The conversation card remains one
     visual surface while header, thread and reply footer gain an operator-set
     flex order. Sidebar-first/last is honoured when the layout stacks. */
  #px-d-card{display:flex;flex-direction:column}
  #px-d-card .d-region{min-width:0}
  #px-d-card .d-region-thread:empty,#px-d-card .d-region-footer:empty{display:none}
  .rq-grid.dl-single-column.dr-sidebar-first .rq-side{order:-2}
  .rq-grid.dl-single-column.dr-sidebar-last .rq-side{order:2}
  @media(max-width:860px){#px-d-grid.dr-sidebar-first .rq-side{order:-2}#px-d-grid.dr-sidebar-last .rq-side{order:2}}
  /* mobile: conversation/form first, info sidebar below (key facts are already in the header chips) */
  /* PHASE_PORTAL_P21 — ⚠ THE DOUBLED `.rq-grid.rq-grid` IS DELIBERATE, DO NOT "TIDY" IT.
     A bare `.rq-grid` here is (0,1,0) and LOSES to the `.rq-grid.dl-*` variants at (0,2,0)
     declared around L1525 — so on a phone the two-column variants never collapsed:
     dl-sidebar-left computed `280px 37px` (the conversation squeezed to 37px) and dl-wide
     computed `0px 340px` (the thread rendered at ZERO width), both overflowing the document.
     Repeating the class lifts this to (0,2,0), which ties the variants and wins on order
     because this rule is later in the stylesheet. Written this way rather than listing the
     six variants so that ANY new dl-* variant collapses on mobile for free — the L1518 note
     explains the matching trap on the desktop side. */
  @media(max-width:860px){.rq-grid.rq-grid{grid-template-columns:1fr}#px-d-grid .rq-side{order:2}#px-d-grid .rq-side .side-card{position:static}}
  /* ⚠ sticky offsets must ride --px-navh (published on every design apply),
     never a hardcoded pixel. 76px only happened to look right against the
     current 63px nav; a denser or taller nav would overlap these, and with a
     non-sticky nav (--px-navh:0) they floated 76px down for no reason. */
  .side-card{padding:18px 20px;position:sticky;top:calc(var(--px-navh,0px) + 13px)}
  .sd-row{display:flex;align-items:center;justify-content:space-between;gap:10px;padding:9px 0;border-bottom:1px solid var(--line-soft)}
  .sd-row:first-child{padding-top:0}
  .sd-l{font-size:11px;font-weight:800;text-transform:uppercase;letter-spacing:.06em;color:var(--ink-3)}
  /* P14 — "Expected resolution / about 3 hours" broke the VALUE across two lines
     ("about 3" / "hours") and made that row 58px against 38px for its siblings.
     The value now stays whole and a long label wraps instead, which reads far
     better than a fractured figure. */
  .sd-v{font-size:12.5px;font-weight:650;color:var(--ink);text-align:right;flex:0 0 auto;white-space:nowrap}
  .sd-l{flex:1 1 auto;min-width:0}
  .sd-actions{padding-top:14px;display:flex;flex-direction:column;gap:8px}
  .sd-actions .btn-ghost{margin:0;padding:11px;font-size:13px}
  .sd-actions .solve{border-color:color-mix(in srgb,var(--ok) 45%,var(--line));color:var(--ok)}
  .sd-actions .solve:hover{background:color-mix(in srgb,var(--ok) 6%,#fff);border-color:var(--ok)}
  /* ═══ Action-button pack: width × shape × look for Mark-resolved / Reopen ═══ */
  .sd-actions.abw-wide{align-items:center}.sd-actions.abw-wide .btn-ghost{width:80%}
  .sd-actions.abw-auto{align-items:flex-start}.sd-actions.abw-auto .btn-ghost{width:auto;padding-left:20px;padding-right:20px}
  .sd-actions.abw-auto #px-reopen-wrap{width:auto}
  .sd-actions.abs-rounded .btn-ghost{border-radius:12px}
  .sd-actions.abs-pill .btn-ghost{border-radius:999px}
  .sd-actions.abs-square .btn-ghost{border-radius:6px}
  .sd-actions.abs-sharp .btn-ghost{border-radius:0}
  .sd-actions.abl-gradient .solve{background:var(--accent-bg,linear-gradient(135deg,var(--accent),var(--accent-d)));color:#fff;border-color:transparent;box-shadow:0 8px 20px -6px color-mix(in srgb,var(--accent) 50%,transparent)}
  .sd-actions.abl-gradient .solve:hover{filter:brightness(1.05);background:var(--accent-bg,linear-gradient(135deg,var(--accent),var(--accent-d)))}
  .sd-actions.abl-solid .solve{background:var(--ok);color:#fff;border-color:transparent}
  .sd-actions.abl-solid .solve:hover{background:var(--ok);filter:brightness(.96)}
  .sd-actions.abl-soft .solve{background:color-mix(in srgb,var(--ok) 15%,transparent);color:var(--ok);border-color:transparent}
  .sd-actions.abl-outline .solve{background:transparent;border:1.5px solid var(--ok);color:var(--ok)}
  .sd-actions.abl-glow .solve{background:var(--ok);color:#fff;border-color:transparent;box-shadow:0 0 0 1px color-mix(in srgb,var(--ok) 40%,transparent),0 8px 22px -4px color-mix(in srgb,var(--ok) 55%,transparent)}
  .sd-actions.abl-ghost .solve{background:transparent;border-color:transparent;color:var(--ok)}
  .sd-actions.abl-ghost .solve:hover{background:color-mix(in srgb,var(--ok) 8%,transparent)}
  /* reopen mirrors the look with the accent hue */
  .sd-actions.abl-gradient #px-reopen{background:var(--accent-bg,linear-gradient(135deg,var(--accent),var(--accent-d)));color:#fff;border-color:transparent}
  .sd-actions.abl-solid #px-reopen{background:var(--accent);color:#fff;border-color:transparent}
  .sd-actions.abl-glow #px-reopen{background:var(--accent);color:#fff;border-color:transparent;box-shadow:0 8px 22px -4px color-mix(in srgb,var(--accent) 50%,transparent)}
  /* ═══ Smart side cards (other tickets / related help / contact / activity) ═══ */
  /* ⚠ THE WRAPPER CARRIES TWO CLASSES AND THEY ARE NOT INTERCHANGEABLE. #px-d-cards is stamped
     `swrap sws-<surface> swe-<empty> [swi-off]` in pxRenderSmartCards() (portal.php). `swrap` is
     STRUCTURAL and always present; `sws-*` is the operator's APPEARANCE pick out of four values
     (elevated | soft | outline | glass, the "Widget surface" control in Portal Studio).

     ⚠ REFERENCE THE WRAPPER AS `.rq-side > .swrap`, NEVER `.rq-side > .sws-elevated`. Every
     structural rule below — the sticky machinery, the dl-dual-sidebar rails, the ds-rail/glass/slab
     surfaces — used to name `.sws-elevated`, which is one of the FOUR surface values, not the
     wrapper. So picking Soft, Outline or Glass silently detached the whole sidebar from its own
     layout engine: the cards fell back to the base `.side-card{position:sticky}` and pinned inside
     the wrapper, riding over one another (the exact failure rejected at "LEAVE THE WRAPPER ALONE"
     below), and dl-dual-sidebar lost its --px-rail-r stagger so both rail cards pinned to one line.
     Only `elevated` — the default, which is why nobody hit it — behaved. Selecting on the surface
     enum belongs to the four `#px-d-cards.sws-*` appearance rules directly beneath this, and
     nowhere else. Class-for-class, so specificity is unchanged from when these rules were tuned. */
  #px-d-cards{display:flex;flex-direction:column;gap:14px;margin-top:14px}
  .smc{padding:16px 18px;transition:transform .18s var(--ease),box-shadow .18s var(--ease),border-color .18s var(--ease),background .18s var(--ease)}
  #px-d-cards.sws-elevated .smc{border-color:color-mix(in srgb,var(--accent) 10%,var(--line));box-shadow:0 16px 38px -31px color-mix(in srgb,var(--ink) 62%,transparent),0 2px 8px -6px rgba(15,23,42,.18)}
  #px-d-cards.sws-elevated .smc:hover{transform:translateY(-1px);box-shadow:0 20px 44px -30px color-mix(in srgb,var(--accent) 34%,var(--ink))}
  #px-d-cards.sws-soft .smc{border-color:transparent;background:color-mix(in srgb,var(--accent) 5%,var(--card));box-shadow:none}
  #px-d-cards.sws-outline .smc{border-width:1.5px;border-color:color-mix(in srgb,var(--accent) 20%,var(--line));box-shadow:none;background:transparent}
  #px-d-cards.sws-glass .smc{background:color-mix(in srgb,var(--card) 78%,transparent);border-color:rgba(255,255,255,.42);box-shadow:0 18px 46px -34px rgba(15,23,42,.58);backdrop-filter:blur(16px) saturate(135%);-webkit-backdrop-filter:blur(16px) saturate(135%)}
  .smc-h{display:flex;align-items:center;gap:8px;font-size:12.5px;font-weight:800;color:var(--ink);margin-bottom:12px;text-transform:uppercase;letter-spacing:.03em}
  .smc-h svg{padding:5px;box-sizing:content-box;border-radius:9px;background:color-mix(in srgb,var(--accent) 9%,transparent)}
  #px-d-cards.swi-off .smc-h svg{display:none}
  .smc-h svg{color:var(--accent);width:15px;height:15px}
  .smc-item{display:block;text-decoration:none;padding:9px 10px;border-radius:9px;transition:.14s var(--ease)}
  .smc-item:hover{background:color-mix(in srgb,var(--accent) 7%,transparent)}
  .smc-it-sub{font-size:13px;font-weight:700;color:var(--ink);line-height:1.35;display:block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  .smc-it-meta{font-size:11.5px;color:var(--ink-3);margin-top:2px;display:flex;align-items:center;gap:6px}
  .smc-empty{font-size:12.5px;line-height:1.55;color:var(--ink-3);padding:10px 11px;border-radius:10px;background:color-mix(in srgb,var(--ink) 3%,transparent);border:1px dashed color-mix(in srgb,var(--ink-3) 20%,transparent)}
  #px-d-cards.swe-quiet .smc-empty{padding:2px 0;border:0;background:transparent;font-size:11.75px;opacity:.72}
  .smc-custom{font-size:13px;line-height:1.65;color:var(--ink-2)}
  .smc-custom>:first-child{margin-top:0}.smc-custom>:last-child{margin-bottom:0}
  .smc-custom a{color:var(--accent);font-weight:750;text-underline-offset:2px}
  .smc-next{display:flex;gap:10px;align-items:flex-start;padding:10px 11px;border-radius:11px;background:linear-gradient(135deg,color-mix(in srgb,var(--accent) 9%,transparent),color-mix(in srgb,var(--accent) 3%,transparent));color:var(--ink-2);font-size:12.75px;line-height:1.55}
  .smc-next b{display:block;color:var(--ink);font-size:12.75px;margin-bottom:2px}
  .smc-contact a{display:flex;align-items:center;gap:9px;padding:8px 10px;border-radius:9px;text-decoration:none;color:var(--ink-2);font-weight:600;font-size:13px}
  .smc-contact a:hover{background:color-mix(in srgb,var(--accent) 7%,transparent);color:var(--accent)}
  /* PHASE_PORTAL_SIDECARDS — agent + CSAT cards */
  .smc-agentrow{display:flex;align-items:center;gap:10px;padding:4px 2px}
  .smc-ava{width:34px;height:34px;border-radius:50%;flex-shrink:0;display:flex;align-items:center;justify-content:center;font-weight:800;font-size:14px;color:#fff;background:linear-gradient(135deg,var(--accent),color-mix(in srgb,var(--accent) 70%,#000))}
  .smc-stars{color:#f59e0b;font-size:14px;letter-spacing:1px}
  .smc-star-off{color:var(--line)}
  .smc-it-sub.smc-over{color:var(--err,#ef4444);font-weight:750}
  /* PHASE_PORTAL_SIDECARD2 — collapsible sidebar cards */
  .smc-collapsible .smc-h{cursor:pointer;justify-content:space-between}
  .smc-collapsible .smc-h::after{content:'▾';font-size:11px;color:var(--ink-3);transition:transform .15s var(--ease);margin-left:auto}
  .smc-folded .smc-h::after{transform:rotate(-90deg)}
  .smc-folded>*:not(.smc-h){display:none}
  /* PHASE_PORTAL_SIDEDRAG — drag-to-reorder side cards */
  .smc-drag{cursor:default}
  .smc-grip{display:inline-flex;align-items:center;cursor:grab;color:var(--ink-3);font-size:14px;line-height:1;margin-right:2px;opacity:.55;transition:opacity .12s var(--ease)}
  .smc-grip:active{cursor:grabbing}
  .smc:hover .smc-grip{opacity:1}
  .smc-dragging{opacity:.5}
  /* PHASE_PORTAL_CMDK — quick-jump command palette */
  .px-cmdk-ov{position:fixed;inset:0;z-index:5000;display:flex;align-items:flex-start;justify-content:center;padding:12vh 16px 16px;background:color-mix(in srgb,var(--ink) 34%,transparent);backdrop-filter:blur(3px);opacity:0;pointer-events:none;transition:opacity .14s var(--ease)}
  .px-cmdk-ov.show{opacity:1;pointer-events:auto}
  .px-cmdk{width:100%;max-width:560px;background:var(--card,#fff);border:1px solid var(--border);border-radius:16px;box-shadow:0 24px 70px -18px rgba(2,6,23,.5);overflow:hidden;transform:translateY(-8px) scale(.99);transition:transform .16s var(--ease)}
  .px-cmdk-ov.show .px-cmdk{transform:none}
  .px-cmdk-top{display:flex;align-items:center;gap:10px;padding:14px 16px;border-bottom:1px solid var(--border)}
  .px-cmdk-top svg{width:18px;height:18px;color:var(--ink-3);flex-shrink:0}
  .px-cmdk-in{flex:1;border:0;outline:0;background:transparent;font-size:15px;color:var(--ink);font-family:inherit}
  .px-cmdk-in::placeholder{color:var(--ink-3)}
  .px-cmdk-esc{font-size:10.5px;font-weight:700;color:var(--ink-3);border:1px solid var(--border);border-radius:6px;padding:2px 6px;letter-spacing:.02em}
  .px-cmdk-list{max-height:min(52vh,440px);overflow-y:auto;padding:6px}
  .px-cmdk-grp{font-size:10.5px;font-weight:800;letter-spacing:.06em;text-transform:uppercase;color:var(--ink-3);padding:10px 10px 4px}
  .px-cmdk-it{display:flex;align-items:center;gap:11px;padding:9px 10px;border-radius:10px;cursor:pointer;text-decoration:none}
  .px-cmdk-it svg{width:17px;height:17px;color:var(--ink-3);flex-shrink:0}
  .px-cmdk-it.sel,.px-cmdk-it:hover{background:color-mix(in srgb,var(--accent) 10%,transparent)}
  .px-cmdk-it.sel svg,.px-cmdk-it:hover svg{color:var(--accent)}
  .px-cmdk-lbl{flex:1;min-width:0;font-size:13.5px;font-weight:650;color:var(--ink);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  .px-cmdk-meta{font-size:11.5px;color:var(--ink-3);flex-shrink:0}
  .px-cmdk-none{padding:22px 12px;text-align:center;font-size:13px;color:var(--ink-3)}
  .smc-folded .smc-h{margin-bottom:0}
  /* ═══ Reply layout (block structure) — distinct from bubble_style ═══ */
  .thread.rl-compact .brow{margin-bottom:10px}.thread.rl-compact .who{margin-bottom:2px;font-size:12.5px}.thread.rl-compact .at{margin-top:3px}
  .thread.rl-spacious .brow{margin-bottom:28px}.thread.rl-spacious .body{line-height:1.8}.thread.rl-spacious .bubble{padding:18px 20px}
  .thread.rl-card-head .who{background:color-mix(in srgb,var(--accent) 6%,transparent);padding:6px 11px;border-radius:8px;display:inline-block;margin-bottom:9px}
  .thread.rl-centered .who{text-align:center;width:100%}.thread.rl-centered .at{text-align:center;width:100%}.thread.rl-centered .bubble{text-align:center}.thread.rl-centered .body{text-align:left;display:inline-block}
  .thread.rl-bordered .bubble{border:1px solid var(--line)!important;box-shadow:none!important;background:var(--card)!important}
  /* P14 — consecutive-author grouping keeps 200-message threads scannable
     without removing semantic author labels from the DOM. */
  .thread.tg-author .brow.bgroup,.thread.tg-day-author .brow.bgroup{margin-top:-9px}
  .thread.tg-author .brow.bgroup .avat,.thread.tg-day-author .brow.bgroup .avat{visibility:hidden}
  .thread.tg-author .brow.bgroup .who,.thread.tg-day-author .brow.bgroup .who{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}
  /* header account (guest link / signed-in menu) */
  .px-acct{position:relative;margin-left:14px;flex-shrink:0}
  .px-acct-btn{display:flex;align-items:center;gap:8px;background:none;border:1px solid var(--line);border-radius:999px;padding:5px 12px 5px 5px;cursor:pointer;font-weight:700;font-size:13px;color:var(--ink);transition:.15s var(--ease)}
  .px-acct-btn:hover{border-color:var(--accent)}
  .px-acct-av{width:26px;height:26px;border-radius:50%;background:var(--accent-bg,var(--accent));color:#fff;display:flex;align-items:center;justify-content:center;font-size:11px;font-weight:800}
  .px-acct-menu{position:absolute;right:0;top:calc(100% + 8px);min-width:190px;background:var(--card);border:1px solid var(--line);border-radius:13px;box-shadow:var(--shadow-lg);padding:6px;display:none;z-index:60}
  .px-acct.open .px-acct-menu{display:block}
  .px-acct-menu button,.px-acct-menu a{display:block;width:100%;text-align:left;background:none;border:none;padding:9px 12px;border-radius:9px;font-size:13px;font-weight:650;color:var(--ink);cursor:pointer;text-decoration:none;transition:background .12s var(--ease)}
  .px-acct-menu button:hover,.px-acct-menu a:hover{background:color-mix(in srgb,var(--accent) 7%,transparent)}
  .px-acct-menu .sep{height:1px;background:var(--line-soft);margin:5px 4px}
  .px-acct-signin{font-weight:750;font-size:13.5px;color:var(--ink-2);text-decoration:none;padding:8px 14px;border:1px solid var(--line);border-radius:999px;transition:.15s var(--ease);white-space:nowrap}
  .px-acct-signin:hover{border-color:var(--accent);color:var(--accent)}
  /* ═══ SP6 — native premium rich-text editor (built fresh, not borrowed) ═══ */
  .rte{border:1px solid var(--line);border-radius:12px;overflow:hidden;transition:border-color .16s var(--ease),box-shadow .16s var(--ease);background:var(--card)}
  .rte:focus-within{border-color:var(--accent);box-shadow:0 0 0 4px color-mix(in srgb,var(--accent) 12%,transparent)}
  .rte-bar{display:flex;align-items:center;gap:1px;flex-wrap:wrap;padding:6px 8px;background:color-mix(in srgb,var(--accent) 3%,var(--line-soft));border-bottom:1px solid var(--line-soft)}
  .rte-b{width:30px;height:30px;display:flex;align-items:center;justify-content:center;border:none;background:none;border-radius:8px;cursor:pointer;color:var(--ink-2);font-size:14px;font-weight:800;transition:.12s var(--ease)}
  .rte-b:hover{background:color-mix(in srgb,var(--accent) 10%,#fff);color:var(--accent)}
  .rte-b svg{width:16px;height:16px}
  .rte-sep{width:1px;height:18px;background:var(--line);margin:0 5px}
  /* PHASE_PORTAL_COMPOSE — emoji picker popover */
  .rte-emoji{position:fixed;z-index:120;background:var(--card);border:1px solid var(--line);border-radius:14px;box-shadow:0 18px 44px -12px rgba(2,6,23,.4);padding:8px;max-height:220px;overflow-y:auto;display:flex;flex-wrap:wrap;gap:2px}
  .rte-emoji button{width:32px;height:32px;border:none;background:none;border-radius:8px;cursor:pointer;font-size:18px;line-height:1;padding:0}
  .rte-emoji button:hover{background:color-mix(in srgb,var(--accent) 12%,transparent)}
  /* PHASE_PORTAL_COMPOSE — rich (WYSIWYG) editable surface, mirrors the textarea look */
  .rte-rich .rte-ce{min-height:var(--rte-h,120px);padding:11px 13px;font-size:14px;line-height:1.55;color:var(--ink);outline:none;overflow-y:auto;max-height:340px}
  .rte-rich .rte-ce:empty::before{content:attr(data-ph);color:var(--ink-3)}
  .rte-rich .rte-ce p{margin:0 0 8px}.rte-rich .rte-ce ul,.rte-rich .rte-ce ol{margin:0 0 8px;padding-left:22px}
  .rte-rich .rte-ce blockquote{margin:0 0 8px;padding-left:12px;border-left:3px solid var(--line);color:var(--ink-2)}
  .rte-rich .rte-ce pre{background:var(--line-soft);padding:8px 10px;border-radius:8px;overflow:auto;font-family:ui-monospace,monospace;font-size:13px}
  .rte-rich .rte-ce a{color:var(--accent);text-decoration:underline}
  /* PHASE_PORTAL_COMPOSE2 — draft-saved note + full-screen compose */
  .p-draft-note{position:fixed;bottom:18px;left:50%;transform:translateX(-50%) translateY(10px);background:var(--ink);color:var(--card);font-size:12px;font-weight:700;padding:6px 14px;border-radius:999px;opacity:0;pointer-events:none;transition:opacity .2s var(--ease),transform .2s var(--ease);z-index:90}
  .p-draft-note.show{opacity:.94;transform:translateX(-50%) translateY(0)}
  .p-fs-btn{margin-top:8px;border:1px solid var(--line);background:var(--card);color:var(--ink-2);border-radius:9px;padding:6px 10px;cursor:pointer;display:inline-flex;align-items:center;gap:6px;font-family:inherit;font-size:12.5px;font-weight:600}
  .p-fs-btn:hover{color:var(--accent);border-color:var(--accent)}
  body.pxfs #pg-new{position:fixed;inset:0;z-index:200;background:var(--bg);overflow:auto;padding:26px 24px;margin:0;max-width:none}
  body.pxfs #pg-new textarea#p-message,body.pxfs #pg-new .rte-ce{min-height:56vh}
  body.pxfs #p-fs-btn{position:fixed;top:16px;right:20px;z-index:201;margin:0}
  .rte-hint{margin-left:auto;font-size:11px;color:var(--ink-3);font-weight:600;padding-right:4px}
  .rte textarea{border:none;border-radius:0;box-shadow:none!important;min-height:130px;resize:vertical;display:block}
  .rte textarea:focus{border:none}
  /* PHASE_PORTAL_COMPOSETABLE — tables in the composer and in rendered message bodies */
  .rte-ce table,.bubble .body table{border-collapse:collapse;width:100%;margin:8px 0;font-size:13px}
  .rte-ce th,.rte-ce td,.bubble .body th,.bubble .body td{border:1px solid var(--line);padding:6px 10px;text-align:left;vertical-align:top}
  .rte-ce th,.bubble .body th{background:color-mix(in srgb,var(--accent) 6%,var(--line-soft));font-weight:700;color:var(--ink)}
  /* PHASE_PORTAL_AIREWRITE — "Improve with AI" composer control */
  .px-airw{position:relative;display:flex;align-items:center;gap:8px;margin-top:8px;flex-wrap:wrap}
  .px-airw-btn{display:inline-flex;align-items:center;gap:6px;border:1px solid color-mix(in srgb,var(--accent) 35%,var(--line));background:color-mix(in srgb,var(--accent) 7%,transparent);color:var(--accent);font-size:12.5px;font-weight:700;font-family:inherit;padding:7px 13px;border-radius:999px;cursor:pointer;transition:.14s var(--ease)}
  .px-airw-btn:hover{background:color-mix(in srgb,var(--accent) 13%,transparent)}
  .px-airw-btn.loading{opacity:.6;cursor:default}
  .px-airw-btn.loading svg{animation:pxspin 1s linear infinite}
  @keyframes pxspin{to{transform:rotate(360deg)}}
  .px-airw-menu{position:absolute;top:calc(100% + 6px);left:0;z-index:40;min-width:180px;background:var(--card,#fff);border:1px solid var(--line);border-radius:12px;box-shadow:0 16px 40px -12px rgba(2,6,23,.4);padding:6px;display:none}
  .px-airw-menu.open{display:block}
  .px-airw-menu button{display:block;width:100%;text-align:left;border:none;background:none;font-family:inherit;font-size:13px;font-weight:600;color:var(--ink-2);padding:9px 11px;border-radius:8px;cursor:pointer}
  .px-airw-menu button:hover{background:color-mix(in srgb,var(--accent) 9%,transparent);color:var(--accent)}
  .px-airw-undo{border:1px solid var(--line);background:var(--card,#fff);color:var(--ink-2);font-size:12px;font-weight:700;font-family:inherit;padding:6px 12px;border-radius:999px;cursor:pointer}
  .px-airw-undo:hover{border-color:var(--accent);color:var(--accent)}
  .px-airw-note{font-size:12px;color:var(--ink-3);opacity:0;transition:opacity .18s var(--ease)}
  .px-airw-note.show{opacity:1}
  /* priority segmented control */
  .prio-seg{display:flex;gap:6px}
  .prio-seg button{flex:1;border:1px solid var(--line);background:var(--card);border-radius:10px;padding:9px 6px;font-size:12.5px;font-weight:700;color:var(--ink-2);cursor:pointer;transition:.14s var(--ease);display:flex;align-items:center;justify-content:center;gap:6px}
  .prio-seg button:hover{border-color:var(--accent)}
  .prio-seg button.on{color:#fff;border-color:transparent}
  .prio-seg button.on[data-p=low]{background:#64748b}
  .prio-seg button.on[data-p=medium]{background:var(--accent)}
  .prio-seg button.on[data-p=high]{background:#f59e0b}
  .prio-seg button.on[data-p=urgent]{background:#ef4444}
  /* ⚠ P20 — SEVERITY IS ENCODED IN FORM, NOT ONLY COLOUR ("encode state in form").
     All four priorities used to be the same 8px circle differing only in hue, so the
     ramp vanished in greyscale and did not read at a glance. Both pxPill and pxPrio
     already print a TEXT label, so WCAG 1.4.1 was met — this is about scannability.
     The form now escalates: hollow -> solid -> solid+ring -> solid+double ring, which
     survives greyscale and any colour-vision deficiency. Colours are unchanged. */
  .prio-dot{width:9px;height:9px;border-radius:50%;box-sizing:border-box;flex:0 0 auto;position:relative}
  .prio-dot.low{background:transparent;border:1.5px solid #64748b}
  .prio-dot.medium{background:var(--accent)}
  .prio-dot.high{background:#f59e0b;box-shadow:0 0 0 2px color-mix(in srgb,#f59e0b 30%,transparent)}
  .prio-dot.urgent{background:#ef4444;box-shadow:0 0 0 2px color-mix(in srgb,#ef4444 34%,transparent),0 0 0 4.5px color-mix(in srgb,#ef4444 15%,transparent)}
  /* signed-in identity chip (replaces name/email for known customers) */
  .idchip{display:flex;align-items:center;gap:11px;padding:11px 14px;border:1px solid var(--line);border-radius:12px;background:color-mix(in srgb,var(--accent) 5%,var(--card));margin-bottom:14px}
  .idchip .idav{width:34px;height:34px;border-radius:50%;flex-shrink:0;display:flex;align-items:center;justify-content:center;font-weight:800;font-size:14px;color:#fff;background:var(--accent-bg,var(--accent))}
  .idchip .idmeta{min-width:0;line-height:1.35}
  /* The two spans are inline inside a display:block .idmeta with nothing between them, so the
     name ran straight into the address:
       "Nabtech Digitalnet Limitednabtechdigitalnet@gmail.com"
     They stay ON ONE LINE as designed — only the missing separation is added, via a margin on
     the name. Deliberately NOT restacked to blocks: that changed the chip's shape, and the
     defect was a missing gap, not a wrong structure. */
  .idchip .idn{font-weight:800;font-size:13.5px;color:var(--ink);margin-right:9px}
  .idchip .ide{font-size:12.5px;color:var(--ink-3);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  .idchip .idedit{margin-left:auto;font-size:12px;font-weight:700;color:var(--accent);background:none;border:none;cursor:pointer;padding:4px 6px;border-radius:7px}
  .idchip .idedit:hover{background:color-mix(in srgb,var(--accent) 12%,transparent)}
  /* ═══ Priority style variants (well-styled dropdown + more; keep segmented as one option) ═══ */
  .prio-c{position:relative}
  /* dropdown — styled native select with a colour dot */
  .prio-drop{position:relative;display:flex;align-items:center}
  .prio-drop .pd-dot{position:absolute;left:14px;width:10px;height:10px;border-radius:50%;pointer-events:none;z-index:1}
  .prio-drop select{width:100%;appearance:none;-webkit-appearance:none;padding:12px 40px 12px 34px;border:1px solid var(--line);border-radius:12px;background:var(--card);font-size:14px;font-weight:700;color:var(--ink);cursor:pointer;transition:.15s var(--ease)}
  .prio-drop select:hover{border-color:var(--accent)}
  .prio-drop select:focus{outline:none;border-color:var(--accent);box-shadow:0 0 0 4px color-mix(in srgb,var(--accent) 16%,transparent)}
  .prio-drop .pd-caret{position:absolute;right:14px;pointer-events:none;color:var(--ink-3)}
  /* pills */
  .prio-pills{display:flex;flex-wrap:wrap;gap:8px}
  .prio-pills button{border:1px solid var(--line);background:var(--card);border-radius:999px;padding:8px 16px;font-size:13px;font-weight:700;color:var(--ink-2);cursor:pointer;transition:.14s var(--ease);display:flex;align-items:center;gap:7px}
  .prio-pills button:hover{border-color:var(--accent)}
  .prio-pills button.on{color:#fff;border-color:transparent}
  .prio-pills button.on[data-p=low]{background:#64748b}.prio-pills button.on[data-p=medium]{background:var(--accent)}.prio-pills button.on[data-p=high]{background:#f59e0b}.prio-pills button.on[data-p=urgent]{background:#ef4444}
  /* flags — radio-style list with a coloured flag */
  .prio-flags{display:flex;flex-direction:column;gap:7px}
  .prio-flags button{display:flex;align-items:center;gap:11px;border:1px solid var(--line);background:var(--card);border-radius:11px;padding:11px 14px;font-size:13.5px;font-weight:700;color:var(--ink);cursor:pointer;text-align:left;transition:.14s var(--ease)}
  .prio-flags button:hover{border-color:var(--accent)}
  .prio-flags button.on{border-color:var(--accent);background:color-mix(in srgb,var(--accent) 7%,var(--card))}
  .prio-flags .pf-flag{width:0;height:0;border-left:9px solid;border-top:6px solid transparent;border-bottom:6px solid transparent;flex-shrink:0}
  .prio-flags .pf-flag.low{border-left-color:#64748b}.prio-flags .pf-flag.medium{border-left-color:var(--accent)}.prio-flags .pf-flag.high{border-left-color:#f59e0b}.prio-flags .pf-flag.urgent{border-left-color:#ef4444}
  .prio-flags .pf-check{margin-left:auto;color:var(--accent);opacity:0;transition:.14s}
  .prio-flags button.on .pf-check{opacity:1}
  /* buttons — big card grid */
  .prio-btns{display:grid;grid-template-columns:repeat(auto-fit,minmax(90px,1fr));gap:8px}
  .prio-btns button{border:1.5px solid var(--line);background:var(--card);border-radius:12px;padding:13px 8px;font-size:13px;font-weight:800;color:var(--ink-2);cursor:pointer;transition:.14s var(--ease);display:flex;flex-direction:column;align-items:center;gap:7px}
  .prio-btns button:hover{border-color:var(--accent)}
  .prio-btns .pb-dot{width:12px;height:12px;border-radius:50%}
  .prio-btns .pb-dot.low{background:#64748b}.prio-btns .pb-dot.medium{background:var(--accent)}.prio-btns .pb-dot.high{background:#f59e0b}.prio-btns .pb-dot.urgent{background:#ef4444}
  .prio-btns button.on{border-color:var(--accent);background:color-mix(in srgb,var(--accent) 8%,var(--card));color:var(--ink)}
  /* slider */
  .prio-slider{padding:6px 2px}
  .prio-slider input[type=range]{width:100%;accent-color:var(--accent)}
  .prio-slider .ps-scale{display:flex;justify-content:space-between;margin-top:6px;font-size:11.5px;font-weight:700;color:var(--ink-3)}
  .prio-slider .ps-val{margin-top:8px;font-size:13px;font-weight:800}
  /* menu — icon dropdown (uses same styled select) reuse .prio-drop */
  /* SP4c — compose sidebar: live KB answers + next steps */
  #pg-new .card{max-width:none}
  #p-new-grid{grid-template-columns:minmax(0,1fr) 300px}
  /* compose_layout positioning — the "answers/next steps" panel is movable */
  #p-new-grid.cl-sidebar-left{grid-template-columns:300px minmax(0,1fr)}
  #p-new-grid.cl-sidebar-left .rq-main{order:2}#p-new-grid.cl-sidebar-left #p-new-side{order:1}
  #p-new-grid.cl-stacked{grid-template-columns:1fr}#p-new-grid.cl-stacked #p-new-side{order:2}
  #p-new-grid.cl-no-sidebar{grid-template-columns:1fr}#p-new-grid.cl-no-sidebar #p-new-side{display:none}
  @media(max-width:860px){#p-new-grid,#p-new-grid.cl-sidebar-left{grid-template-columns:1fr}#p-new-side{order:2}}
  .sd-head{display:flex;align-items:center;gap:8px;font-size:13px;font-weight:800;color:var(--ink);margin-bottom:12px}
  .sd-head svg{color:var(--accent)}
  .sg-list{display:flex;flex-direction:column;gap:8px}
  .sg-empty{font-size:12.5px;color:var(--ink-3);line-height:1.55}
  .sg-item{display:block;padding:10px 12px;border:1px solid var(--line-soft);border-radius:11px;text-decoration:none;transition:.14s var(--ease);animation:pdIn .2s ease}
  .sg-item:hover{border-color:color-mix(in srgb,var(--accent) 35%,var(--line));background:color-mix(in srgb,var(--accent) 4%,transparent)}
  .sg-t{font-size:13px;font-weight:700;color:var(--ink);display:block}
  .sg-item:hover .sg-t{color:var(--accent)}
  .sg-x{font-size:11.5px;color:var(--ink-3);display:block;margin-top:2px;overflow:hidden;text-overflow:ellipsis;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical}
  /* suggest_style variants */
  .sg-list.ss-cards .sg-item{border:1px solid var(--line);border-radius:13px;padding:13px 14px;box-shadow:var(--shadow-sm);position:relative;padding-right:34px}
  .sg-list.ss-cards .sg-item:hover{transform:translateY(-2px);box-shadow:var(--shadow-md)}
  .sg-list.ss-cards .sg-arr{position:absolute;right:12px;top:50%;transform:translateY(-50%);color:var(--ink-3);transition:.14s var(--ease)}
  .sg-list.ss-cards .sg-item:hover .sg-arr{color:var(--accent);right:9px}
  .sg-list.ss-compact{gap:2px}
  .sg-list.ss-compact .sg-item{border:none;border-radius:7px;padding:7px 9px}
  .sg-list.ss-compact .sg-t{font-size:12.5px;font-weight:600}
  .sg-list.ss-banner{gap:0;border:1px solid color-mix(in srgb,var(--accent) 25%,var(--line));border-radius:13px;overflow:hidden;background:color-mix(in srgb,var(--accent) 4%,var(--card))}
  .sg-list.ss-banner .sg-banner-h{font-size:12px;font-weight:800;color:var(--accent);padding:10px 13px;border-bottom:1px solid color-mix(in srgb,var(--accent) 18%,var(--line))}
  .sg-list.ss-banner .sg-item{border:none;border-radius:0;border-bottom:1px solid var(--line-soft)}
  .sg-list.ss-banner .sg-item:last-child{border-bottom:none}
  .nx-steps{list-style:none;margin:0;padding:0;counter-reset:nx;display:flex;flex-direction:column;gap:12px}
  .nx-steps li{position:relative;padding-left:34px;counter-increment:nx}
  .nx-steps li::before{content:counter(nx);position:absolute;left:0;top:1px;width:24px;height:24px;border-radius:50%;background:color-mix(in srgb,var(--accent) 10%,var(--line-soft));color:var(--accent);font-size:12px;font-weight:800;display:flex;align-items:center;justify-content:center}
  .nx-steps b{display:block;font-size:12.5px;color:var(--ink)}
  .nx-steps i{font-style:normal;display:block;font-size:11.5px;color:var(--ink-3);margin-top:1px;line-height:1.5}
  @media(prefers-reduced-motion:reduce){.btn,.req,.btn-ghost,.reqfilters button,.pcat,.pcatr,.cta-card{transition:none}.btn:hover,.req:hover,.pcat:hover,.pcatr:hover,.cta-card:hover{transform:none}}

  /* ═══ PHASE_PORTAL_P24 — ONE AUTHORITATIVE reduced-motion guard ═══
     Measured before writing this: 53 animation rules with only 10 guarded, and 131 transition
     rules with NONE guarded. 21 of the unguarded animations were INFINITE loops (skeleton
     shimmers, loading dots/pulse/bar, a 7s halo on the sign-in page) and 54 transitions moved
     an element via `transform` — precisely the motion `prefers-reduced-motion` exists to stop
     for vestibular disorders. The twelve hand-written guards above are spot-fixes; this is the
     floor beneath all of them, so a NEW animation is covered the day it is written instead of
     waiting to be noticed.

     ⚠ `.01ms`, NEVER `0s`. A zero duration means `transitionend` / `animationend` NEVER FIRE,
     which silently strands any code that waits on them. 0.01ms still fires them on the next
     tick. (Nothing in portal.php listens for those today — verified — but this rule outlives
     that fact, and the whole point is that it covers code not yet written.)

     ⚠ `animation-iteration-count:1` is what actually stops the 21 infinite loops; shortening
     the duration alone would leave them looping forever, just faster.

     scroll-behavior is included because the portal smooth-scrolls in 6 places. */
  @media (prefers-reduced-motion: reduce){
    *,*::before,*::after{
      animation-duration:.01ms!important;
      animation-iteration-count:1!important;
      transition-duration:.01ms!important;
      scroll-behavior:auto!important;
    }
  }

/* ══════════════════════════════════════════════════════════════════════════════════════
   PHASE_PORTAL_TKLIST_WHMCS — client-area style request list.
   Four opt-in controls, each inert until the operator turns it on in the Studio:
   the reference number inside the subject, sortable headings, the "View" dropdown,
   and one word for the finished state (that last one needs no CSS).
   ══════════════════════════════════════════════════════════════════════════════════════ */

/* — Reference number folded into the subject: "#SBA-455783 - i need help" ————————————
   The number is the quieter half. It must NOT shrink below the subject's own size or the
   row loses its scan line, so it stays at the inherited size and drops only in weight and
   contrast. The separator is its own span so a design can hide it without touching either
   side (some brands prefer "#ID  subject" with spacing alone). */
.rtable .rt-sub .rt-num{font-weight:600;color:var(--ink-3,var(--ink-2,#64748b));font-variant-numeric:tabular-nums}
.rtable .rt-sub .rt-nsep{color:var(--ink-3,var(--ink-2,#94a3b8))}
/* The subject cell ellipsises. Without this the number is the part that gets clipped,
   which is the one piece a customer reads out on the phone. */
.rtable .rt-sub .rt-num,.rtable .rt-sub .rt-nsep{white-space:nowrap;flex:none}

/* — Sortable column headings ————————————————————————————————————————————————————————
   The heading is a <th>, not a button, so it needs its own affordance and focus ring. */
.rtable thead th.rt-sortable{cursor:pointer;user-select:none;position:relative}
.rtable thead th.rt-sortable:hover{color:var(--ink,#0f172a)}
.rtable thead th.rt-sortable:focus-visible{outline:2px solid var(--accent);outline-offset:-2px;border-radius:4px}
/* Reserve the arrow's width at all times so sorting a column does not nudge the heading
   text sideways — that shift reads as the table twitching on every click. */
.rtable thead th.rt-sortable .rt-sarrow{display:inline-block;width:12px;height:12px;margin-left:6px;vertical-align:-1px;opacity:0;transition:opacity .12s var(--ease,ease)}
.rtable thead th.rt-sortable:hover .rt-sarrow{opacity:.45}
.rtable thead th.rt-sortable .rt-sarrow.on{opacity:1}
/* Drawn with borders rather than a glyph: a caret character renders at a different size in
   every font a design might pick, and these tables restyle their heading font freely. */
.rtable thead th.rt-sortable .rt-sarrow::after{
  content:"";position:absolute;top:50%;margin-top:-2px;
  border-left:4px solid transparent;border-right:4px solid transparent;
}
.rtable thead th.rt-sortable .rt-sarrow.asc::after{border-bottom:5px solid currentColor}
.rtable thead th.rt-sortable .rt-sarrow.desc::after{border-top:5px solid currentColor}
/* Both affordances can be on at once. The resize grip owns the right edge, so the arrow
   moves in to keep them from overlapping. */
.rtable.rt-cust thead th.rt-sortable .rt-sarrow{margin-right:9px}

/* — "View" dropdown filter ——————————————————————————————————————————————————————————
   Inherits the portal's own field styling; it is a control, not a nav element. */
.px-vsel{display:inline-flex;align-items:center;gap:9px}
.px-vsel label{font-size:13.5px;font-weight:600;color:var(--ink-2,#475569)}
.px-vselect{
  appearance:none;-webkit-appearance:none;
  padding:7px 30px 7px 11px;font:inherit;font-size:13.5px;line-height:1.35;
  color:var(--ink,#0f172a);background:var(--surface,#fff);
  border:1px solid var(--line,#e2e8f0);border-radius:var(--radius-sm,8px);
  cursor:pointer;
  /* the caret is a background image so no extra element is needed inside a <select> */
  background-image:linear-gradient(45deg,transparent 50%,currentColor 50%),linear-gradient(135deg,currentColor 50%,transparent 50%);
  background-position:calc(100% - 15px) 52%,calc(100% - 10px) 52%;
  background-size:5px 5px,5px 5px;background-repeat:no-repeat;
}
.px-vselect:hover{border-color:color-mix(in srgb,var(--accent) 40%,var(--line,#e2e8f0))}
.px-vselect:focus-visible{outline:2px solid var(--accent);outline-offset:1px}


/* ══════════════════════════════════════════════════════════════════════════════════════════
   PHASE_PORTAL_RAIL_LOOKS — five STRUCTURAL rail designs.

   These change the layout, not the palette. Every one inherits colour from the operator's
   existing settings (--accent, --card, --ink*, --line, --radius*), so a design never fights
   the Theme or Look pack sections and never hardcodes a brand colour.

   ⚠ THE GLASSMORPHISM LOOK PACK USES !important.
   "Effects & glassmorphism" sets `.card{background:…!important}` over a selector list that
   includes the rail. !important can only be answered with !important, so any design that owns
   its surface says so explicitly and is qualified with .dp-wrap to keep the intent readable.
   Onyx failed loudly on this during testing: ink inverted while the background did not, which
   left near-invisible text. Dark designs therefore set background and colour in one rule.

   Shared hook: pxRailPrepLinks() guarantees every .dp-rail-link contains
   `<svg> + <span class="dpr-l">label</span>`, so these can lay the two out freely.
   ══════════════════════════════════════════════════════════════════════════════════════════ */

/* ── 1. TILES — two-column icon grid ────────────────────────────────────────────────────── */
/* Done entirely in CSS. An earlier attempt moved the links into a wrapper div in JS and was
   wrong twice over: the operator's extra links live in their OWN container (.rq-rail-extra,
   rebuilt on every render), so only 2 of 7 links were ever collected, and anything moved out
   of that container would be destroyed on the next rebuild. Gridding the rail itself and
   spanning the non-link children handles both containers and survives the rebuild. */
.dp-wrap .dp-rail.rs-tiles{
  display:grid;grid-template-columns:1fr 1fr;gap:7px;align-content:start;
}
/* Everything that is not a tile spans the full width. */
.dp-rail.rs-tiles .dp-rail-title,
.dp-rail.rs-tiles .dp-hours,
.dp-rail.rs-tiles .dpr-id{grid-column:1/-1}
/* display:contents rather than a nested grid, so the operator's extra links join the SAME grid
   as the rail's own. A nested grid left the last rail link alone on its row with an empty cell
   beside it, because the two grids could not share rows. Verified in-browser both ways. */
.dp-rail.rs-tiles .rq-rail-extra{display:contents}
.dp-rail.rs-tiles .dp-rail-link{
  display:flex;flex-direction:column;align-items:center;justify-content:center;gap:7px;
  text-align:center;padding:15px 9px;min-height:82px;
  border:1px solid var(--line,#e2e8f0);border-radius:var(--radius-sm,10px);
  background:color-mix(in srgb,var(--accent) 4%,transparent);
}
.dp-rail.rs-tiles .dp-rail-link .dpr-l{font-size:12px;line-height:1.25;font-weight:600}
.dp-rail.rs-tiles .dp-rail-link svg{width:20px;height:20px}
.dp-rail.rs-tiles .dp-rail-link:hover{
  background:color-mix(in srgb,var(--accent) 11%,transparent);
  border-color:color-mix(in srgb,var(--accent) 40%,transparent);
}
/* The CTA earns the full width — it is the one action, not one of six equals. */
.dp-rail.rs-tiles .dp-rail-cta{
  grid-column:1/-1;flex-direction:row;min-height:0;padding:11px 13px;
  background:var(--accent);border-color:var(--accent);color:#fff;
}
.dp-rail.rs-tiles .dp-rail-cta:hover{background:color-mix(in srgb,var(--accent) 88%,#000);color:#fff}

/* ── 2. STACK — every link its own card, icon plate + chevron ───────────────────────────── */
.dp-rail.rs-stack .dp-rail-link{
  position:relative;display:flex;align-items:center;gap:11px;
  padding:11px 30px 11px 11px;margin-bottom:7px;
  border:1px solid var(--line,#e2e8f0);border-radius:var(--radius-sm,10px);
  background:var(--card,#fff);
  box-shadow:0 1px 2px rgba(15,23,42,.04);
  transition:transform .14s var(--ease,ease),box-shadow .14s var(--ease,ease);
}
/* The icon sits on a tinted plate so the row reads as a card, not a list item. */
.dp-rail.rs-stack .dp-rail-link svg,
.dp-rail.rs-stack .dp-rail-link > i{
  /* `i` as well as `svg`: an operator-named icon renders as a Font Awesome <i>, and plating
     only the svg left those rows visibly inconsistent with the rest. */
  flex:none;box-sizing:content-box;padding:7px;border-radius:8px;width:17px;height:17px;
  display:inline-flex;align-items:center;justify-content:center;font-size:15px;
  background:color-mix(in srgb,var(--accent) 12%,transparent);color:var(--accent);
}
/* Chevron drawn from borders — a glyph would change size with every design's font. */
.dp-rail.rs-stack .dp-rail-link::after{
  content:"";position:absolute;right:13px;top:50%;
  width:6px;height:6px;margin-top:-4px;
  border-right:2px solid var(--ink-3,#94a3b8);border-bottom:2px solid var(--ink-3,#94a3b8);
  rotate:-45deg;
}
.dp-rail.rs-stack .dp-rail-link:hover{transform:translateX(2px);box-shadow:0 6px 16px -6px rgba(15,23,42,.18)}
.dp-rail.rs-stack .dp-rail-cta{background:var(--accent);border-color:var(--accent);color:#fff}
.dp-rail.rs-stack .dp-rail-cta svg{background:rgba(255,255,255,.22);color:#fff}
.dp-rail.rs-stack .dp-rail-cta::after{border-color:rgba(255,255,255,.85)}

/* ── 3. IDENTITY — leads with the signed-in customer ────────────────────────────────────── */
/* Injected by pxRailIdentity() and omitted entirely for a guest, so this never renders an
   empty avatar. */
.dp-rail.rs-identity .dpr-id{
  display:flex;align-items:center;gap:11px;
  padding:0 0 13px;margin-bottom:11px;border-bottom:1px solid var(--line,#e2e8f0);
}
.dp-rail.rs-identity .dpr-id-av{
  flex:none;width:40px;height:40px;border-radius:50%;
  display:inline-flex;align-items:center;justify-content:center;
  font-size:13.5px;font-weight:800;letter-spacing:.02em;color:#fff;
  background:linear-gradient(145deg,var(--accent),color-mix(in srgb,var(--accent) 55%,#000));
  box-shadow:0 2px 8px -2px color-mix(in srgb,var(--accent) 55%,transparent);
}
.dp-rail.rs-identity .dpr-id-tx{display:flex;flex-direction:column;min-width:0;gap:1px}
.dp-rail.rs-identity .dpr-id-tx b{
  font-size:13.5px;font-weight:700;color:var(--ink,#0f172a);
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
}
.dp-rail.rs-identity .dpr-id-tx i{font-style:normal;font-size:11.5px;color:var(--ink-3,#64748b)}
/* Section-label treatment on the title, so the identity block reads as the header and the
   title below it reads as a group heading. */
.dp-rail.rs-identity .dp-rail-title{
  text-transform:uppercase;font-size:10.5px;letter-spacing:.09em;color:var(--ink-3,#64748b);
}
.dp-rail.rs-identity .dp-rail-link{border-radius:8px}
.dp-rail.rs-identity .dp-rail-link:hover{background:color-mix(in srgb,var(--accent) 9%,transparent)}

/* ── 4. ICONS — narrow icon-only column, label on hover ─────────────────────────────────── */
/* The rail's WIDTH comes from the grid, so the design has to shrink the column too, not just
   its contents — otherwise the labels vanish and leave a 260px empty gutter. */
.dp-wrap.has-rail:has(.dp-rail.rs-icons){grid-template-columns:76px minmax(0,1fr)}
.dp-wrap.has-rail.rail-right:has(.dp-rail.rs-icons){grid-template-columns:minmax(0,1fr) 76px}
/* ⚠ THE FLYOUT NEEDS THE RAIL LIFTED, NOT THE LABEL.
   .dp-rail is position:sticky, and sticky CREATES A STACKING CONTEXT — so a z-index on the
   label is confined inside the rail. The rail itself was z-index:auto and sits BEFORE .dp-main
   in the DOM, so the whole rail (flyout included) painted underneath the content. Raising the
   rail is what puts the label on top; measured in-browser, nothing clips it. */
.dp-rail.rs-icons{padding:11px 9px;align-items:center;z-index:30}
.dp-rail.rs-icons .dp-rail-title{display:none}
.dp-rail.rs-icons .dp-rail-link{
  position:relative;justify-content:center;padding:11px;margin-bottom:5px;border-radius:10px;
}
.dp-rail.rs-icons .dp-rail-link svg{width:20px;height:20px}
/* A link the operator gave no icon has nothing to draw and rendered as an empty box. Stand in
   with its first letter, carried on data-init by pxRailPrepLinks(). */
.dp-rail.rs-icons .dp-rail-link:not(:has(svg)):not(:has(i))::before{
  content:attr(data-init);
  display:inline-flex;align-items:center;justify-content:center;
  width:20px;height:20px;border-radius:6px;font-size:11.5px;font-weight:800;
  background:color-mix(in srgb,var(--accent) 14%,transparent);color:var(--accent);
}
/* Label becomes a hover flyout. Positioned, not display:none, so screen readers still read it. */
.dp-rail.rs-icons .dp-rail-link .dpr-l{
  position:absolute;left:calc(100% + 9px);top:50%;translate:0 -50%;
  white-space:nowrap;padding:6px 10px;border-radius:7px;font-size:12px;font-weight:600;
  background:var(--ink,#0f172a);color:#fff;
  opacity:0;pointer-events:none;transition:opacity .13s var(--ease,ease);
  z-index:20;
}
.dp-rail.rs-icons .dp-rail-link:hover .dpr-l,
.dp-rail.rs-icons .dp-rail-link:focus-visible .dpr-l{opacity:1}
/* A right-hand rail must flip the flyout inward or it opens off-screen. */
.rail-right .dp-rail.rs-icons .dp-rail-link .dpr-l{left:auto;right:calc(100% + 9px)}
.dp-rail.rs-icons .dp-rail-cta{background:var(--accent);color:#fff}
/* The hours card cannot fit 76px, but hiding it threw away the one thing a customer most wants
   at a glance: whether anyone is there. It becomes a status tile matching the icon tiles, with
   the full card as a hover flyout — the same interaction the labels use, so the rail has one
   behaviour rather than two.
   The dot colour is driven by :has() on the badge the server already sets, so open/closed can
   never disagree with the badge inside the flyout. */
.dp-rail.rs-icons .dp-hours{
  position:relative;display:flex;align-items:center;justify-content:center;
  width:100%;padding:11px 0 0;margin-top:7px;
  border:0;border-top:1px solid var(--line,#e2e8f0);border-radius:0;
  background:none!important;box-shadow:none;
}
/* The tile face: a ring with a status dot inside it. */
.dp-rail.rs-icons .dp-hours::before{
  content:"";width:20px;height:20px;border-radius:50%;
  border:2px solid color-mix(in srgb,var(--ink-3,#94a3b8) 45%,transparent);
  background:radial-gradient(circle at 50% 50%, currentColor 0 4px, transparent 4px);
  color:var(--ink-3,#94a3b8);
}
.dp-rail.rs-icons .dp-hours:has(.dp-hours-badge.is-open)::before{
  color:#10b981;border-color:color-mix(in srgb,#10b981 55%,transparent);
  box-shadow:0 0 0 3px color-mix(in srgb,#10b981 18%,transparent);
}
.dp-rail.rs-icons .dp-hours:has(.dp-hours-badge.is-closed)::before{
  color:var(--ink-3,#94a3b8);
}
/* The whole card body becomes the flyout. .dph-body is display:contents everywhere else, which
   is why it exists — there is no other single element wrapping the card's contents. */
.dp-rail.rs-icons .dp-hours > .dph-body{
  position:absolute;left:calc(100% + 9px);top:50%;translate:0 -50%;
  display:block;width:210px;padding:13px;text-align:left;
  border:1px solid var(--line,#e2e8f0);border-radius:12px;
  /* ⚠ DELIBERATELY NOT var(--card). With the glassmorphism look pack on, the card token is
     translucent, and a translucent FLYOUT is unreadable — the request table showed straight
     through the opening hours. A flyout overlays content, so it has to be opaque. Both themes
     are named explicitly rather than derived, and a blur backs it up on top of that. */
  background:#fff;
  -webkit-backdrop-filter:blur(12px);backdrop-filter:blur(12px);
  box-shadow:0 18px 40px -14px rgba(15,23,42,.28);
  opacity:0;pointer-events:none;transition:opacity .13s var(--ease,ease);
  z-index:31;
}
:root[data-theme="dark"] .dp-rail.rs-icons .dp-hours > .dph-body{background:#0f172a;border-color:rgba(255,255,255,.14)}
@media (prefers-color-scheme:dark){
  :root:not([data-theme="light"]) .dp-rail.rs-icons .dp-hours > .dph-body{background:#0f172a;border-color:rgba(255,255,255,.14)}
}
/* The same applies to the icon-label flyout, for the same reason. */
.dp-rail.rs-icons .dp-rail-link .dpr-l{background:#0f172a}
.dp-rail.rs-icons .dp-hours:hover > .dph-body,
.dp-rail.rs-icons .dp-hours:focus-within > .dph-body{opacity:1;pointer-events:auto}
/* Mirrored for a right-hand rail, or the flyout opens off the edge of the page. */
.rail-right .dp-rail.rs-icons .dp-hours > .dph-body{left:auto;right:calc(100% + 9px)}
/* On a phone the rail is a full-width row again, so the flyout has no room to the side —
   the card simply reads inline as it does in every other design. */
@media(max-width:760px){
  .dp-rail.rs-icons .dp-hours{display:none}
}
@media(max-width:760px){
  /* Back to a full-width row on a phone: a 76px column beside content is a desktop idea. */
  .dp-wrap.has-rail:has(.dp-rail.rs-icons),
  .dp-wrap.has-rail.rail-right:has(.dp-rail.rs-icons){grid-template-columns:1fr}
  .dp-rail.rs-icons{flex-direction:row;flex-wrap:wrap;justify-content:flex-start}
  .dp-rail.rs-icons .dp-rail-link .dpr-l{display:none}
}

/* ── 5. CONSOLE — dark operations panel with live counts ────────────────────────────────── */
.dp-wrap .dp-rail.rs-console{
  --ink:#f1f5f9;--ink-2:#cbd5e1;--ink-3:#94a3b8;--line:rgba(255,255,255,.1);
  color:#f1f5f9;border:1px solid rgba(255,255,255,.1);border-radius:12px;
  background:linear-gradient(168deg,#111827 0%,#030712 100%)!important;
  box-shadow:inset 0 1px 0 rgba(255,255,255,.06);
}
.dp-rail.rs-console .dp-rail-title{
  font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;
  text-transform:uppercase;font-size:10.5px;letter-spacing:.12em;color:#64748b;
  padding-bottom:9px;border-bottom:1px solid rgba(255,255,255,.09);
}
.dp-rail.rs-console .dp-rail-link{
  color:#cbd5e1;border-radius:6px;
  font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:12.5px;
}
.dp-rail.rs-console .dp-rail-link:hover{background:rgba(255,255,255,.07);color:#f8fafc}
.dp-rail.rs-console .dp-rail-link svg{color:#64748b}
.dp-rail.rs-console .dp-rail-link:hover svg{color:var(--accent)}
.dp-rail.rs-console .dp-rail-cta{
  color:#fff;background:color-mix(in srgb,var(--accent) 90%,#000);border-radius:7px;
}
.dp-rail.rs-console .dp-rail-cta:hover{background:var(--accent)}
.dp-rail.rs-console .dp-rail-cta svg{color:#fff}
/* Live open count, injected by pxRailCounts() and absent when zero rather than showing "0". */
.dp-rail.rs-console .dpr-c{
  margin-left:auto;flex:none;
  min-width:20px;padding:1px 6px;border-radius:999px;
  font-size:11px;font-weight:700;text-align:center;
  background:color-mix(in srgb,var(--accent) 26%,transparent);
  color:#fff;border:1px solid color-mix(in srgb,var(--accent) 45%,transparent);
}
.dp-rail.rs-console .dp-hours{
  background:rgba(255,255,255,.04);border:1px solid rgba(255,255,255,.09);color:#cbd5e1;
}
.dp-rail.rs-console .dp-hours-t{color:#64748b}
.dp-rail.rs-console .dp-hours-time{color:#f8fafc}

/* .dph-body wraps every hours design's content. display:contents makes it invisible to layout,
   so no design sees it — it exists purely so the ICONS rail has one element to turn into a
   hover flyout. Overridden to position:absolute there. */
.dp-hours > .dph-body{display:contents}

/* ══ OPENING HOURS — five structural designs ══════════════════════════════════════════════
   Colour is inherited (--accent / --card / --ink* / --line), never hardcoded, so each of these
   still follows the Theme and Look pack the operator chose. Only CONSOLE sets its own ink, and
   it sets background in the same rule so the two can never disagree. */

/* ── 1. CONSOLE — dark status panel, mono clock, live pulse ─────────────────────────────── */
.dp-rail .dp-hours.hs-console{
  color:#e2e8f0;border:1px solid rgba(255,255,255,.1);border-radius:12px;
  background:linear-gradient(165deg,#111827 0%,#030712 100%)!important;
  box-shadow:inset 0 1px 0 rgba(255,255,255,.06);
}
.dp-hours.hs-console .dp-hours-t{color:#94a3b8;text-transform:uppercase;letter-spacing:.1em;font-size:10.5px}
/* Tabular mono: a clock that reflows as its digits change reads as broken. */
.dp-hours.hs-console .dp-hours-time{
  font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;
  font-variant-numeric:tabular-nums;font-size:18px;font-weight:700;color:#f8fafc;
}
.dp-hours.hs-console .dp-hours-days,.dp-hours.hs-console .dp-hours-tz{color:#94a3b8}
.dp-hours.hs-console .dp-hours-note{color:#cbd5e1}
.dp-hours.hs-console .dp-hours-badge{
  position:relative;padding-left:20px;background:rgba(255,255,255,.08)!important;
  color:#f1f5f9;border:1px solid rgba(255,255,255,.14);
}
.dp-hours.hs-console .dp-hours-badge::before{
  content:"";position:absolute;left:8px;top:50%;margin-top:-3px;
  width:6px;height:6px;border-radius:50%;background:currentColor;
}
.dp-hours.hs-console .dp-hours-badge.is-open{color:#34d399}
.dp-hours.hs-console .dp-hours-badge.is-closed{color:#94a3b8}
/* Only OPEN pulses. A pulsing "closed" dot reads as a fault light. */
.dp-hours.hs-console .dp-hours-badge.is-open::before{animation:pxHoursPulse 2s ease-in-out infinite}
@keyframes pxHoursPulse{0%,100%{box-shadow:0 0 0 0 color-mix(in srgb,#34d399 70%,transparent)}50%{box-shadow:0 0 0 5px transparent}}
@media(prefers-reduced-motion:reduce){.dp-hours.hs-console .dp-hours-badge.is-open::before{animation:none}}

/* ── 2. WEEK — a row per day, today marked ──────────────────────────────────────────────── */
.dph-week{display:flex;flex-direction:column;margin:9px 0 11px;border-top:1px solid var(--line,#e2e8f0)}
.dph-wrow{
  display:flex;align-items:center;justify-content:space-between;gap:9px;
  padding:6px 0;border-bottom:1px solid var(--line,#e2e8f0);font-size:12.5px;
}
.dph-wd{font-weight:600;color:var(--ink-2,#475569)}
.dph-wh{color:var(--ink,#0f172a);font-variant-numeric:tabular-nums}
/* A closed day is shown, not hidden — "closed Sunday" is what the customer came to find out. */
.dph-wrow.is-off .dph-wd,.dph-wrow.is-off .dph-wh{color:var(--ink-3,#94a3b8)}
.dph-wrow.is-today{
  margin-inline:-6px;padding-inline:6px;border-radius:6px;
  background:color-mix(in srgb,var(--accent) 10%,transparent);
}
.dph-wrow.is-today .dph-wd{color:var(--accent);font-weight:800}
/* Collapsed by default: only today shows, so the rail stays as short as the content beside it.
   Seven rows made the sidebar taller than the request list. */
.dp-hours.hs-week.dph-wk-collapsible:not(.dph-wk-open) .dph-wrow:not(.is-today){display:none}
/* With one row visible the top border and the row's own bottom border double up. */
.dp-hours.hs-week.dph-wk-collapsible:not(.dph-wk-open) .dph-week{border-top:0}
.dp-hours.hs-week.dph-wk-collapsible:not(.dph-wk-open) .dph-wrow.is-today{border-bottom:0}
.dph-wk-more{
  display:inline-flex;align-items:center;gap:6px;
  margin:2px 0 9px;padding:4px 9px 4px 5px;
  border:1px solid var(--line,#e2e8f0);border-radius:999px;
  background:none;cursor:pointer;font:inherit;font-size:11.5px;font-weight:700;
  color:var(--ink-3,#64748b);
}
.dph-wk-more:hover{color:var(--accent);border-color:color-mix(in srgb,var(--accent) 40%,transparent)}
.dph-wk-more:focus-visible{outline:2px solid var(--accent);outline-offset:1px}
/* The plus/minus is drawn from two bars so it needs no glyph font and can animate. */
.dph-wk-ic{position:relative;width:14px;height:14px;border-radius:4px;flex:none;
  background:color-mix(in srgb,var(--accent) 12%,transparent)}
.dph-wk-ic::before,.dph-wk-ic::after{
  content:"";position:absolute;left:50%;top:50%;background:currentColor;border-radius:1px;
  translate:-50% -50%;transition:opacity .12s var(--ease,ease);
}
.dph-wk-ic::before{width:8px;height:1.5px}
.dph-wk-ic::after{width:1.5px;height:8px}
/* Expanded: the vertical bar goes, leaving a minus. */
.dph-wk-open .dph-wk-ic::after{opacity:0}

/* ⚠ THE SUB-HERO BAND MUST SHARE THE PAGE'S CONTENT COLUMN.
   The band is full-bleed, but .phero caps its inner column at --px-cw (the HERO content width,
   1140px here) while the page container .wrap uses --px-page-w (1320px). Measured in-browser:
   the heading and breadcrumb started at 173px while the sidebar below them started at 73px, so
   the band looked indented against its own page. Match the PAGE token, and the 20px inline
   padding already agrees with .wrap's. Scoped to #px-subhero so the real hero on the landing
   page keeps its narrower, deliberately centred measure. */
#px-subhero .phero{max-width:var(--px-page-w,1320px)}
/* Two things were indenting the band, and fixing only the first did nothing.
   The BAND DESIGN also pads the unit: .phu-arc uses `padding:calc(50vw - min(50vw,560px))`,
   which is 160px at a 1440 viewport and centres content to its own 1120px measure. Each of the
   15 band designs picks a different figure, so the heading's left edge moved with the design
   rather than with the page. Zeroing the INLINE padding hands alignment to .phero above, which
   now shares the page column — block padding is untouched, so the band keeps its height (that
   comes from .psh-h-* with !important anyway). */
#px-subhero .phero-unit{padding-inline:0}

/* ── 3. COUNTDOWN — time to the next boundary as the headline ───────────────────────────── */
.dph-cd{display:flex;flex-direction:column;gap:1px;margin:7px 0 3px}
.dph-cd-k{font-size:11px;text-transform:uppercase;letter-spacing:.07em;color:var(--ink-3,#64748b);font-weight:700}
.dph-cd-v{
  font-size:24px;font-weight:800;line-height:1.05;color:var(--accent);
  font-variant-numeric:tabular-nums;
}
.dph-cd-sub{font-size:12px;color:var(--ink-3,#64748b);margin-bottom:7px;font-variant-numeric:tabular-nums}

/* ── 4. DIAL — the window inside a ring, badge on the rim ───────────────────────────────── */
.dph-dial{position:relative;display:flex;flex-direction:column;align-items:center;margin:11px 0 13px}
.dph-dial-ring{
  width:118px;height:118px;border-radius:50%;
  display:flex;flex-direction:column;align-items:center;justify-content:center;gap:1px;
  /* Two rings: a solid hairline plus a soft accent halo outside it. */
  border:2px solid color-mix(in srgb,var(--accent) 30%,transparent);
  box-shadow:0 0 0 7px color-mix(in srgb,var(--accent) 8%,transparent);
  background:radial-gradient(70% 70% at 50% 30%, color-mix(in srgb,var(--accent) 10%,transparent), transparent 72%);
}
.dph-dial-t{font-size:15px;font-weight:800;color:var(--ink,#0f172a);font-variant-numeric:tabular-nums;line-height:1.15}
.dph-dial-d{font-size:10.5px;text-transform:uppercase;letter-spacing:.09em;color:var(--ink-3,#94a3b8)}
/* On the rim, overlapping the ring — hence the ring being its own element. */
.dph-dial .dp-hours-badge{margin-top:-11px;position:relative;z-index:2}

/* ── 5. STRIP — one compact row ─────────────────────────────────────────────────────────── */
/* Title and timezone are dropped rather than wrapped: at this density they are the least
   load-bearing lines, and keeping them forced the second row the design exists to avoid. */
.dp-hours.hs-strip{
  display:flex;align-items:center;gap:9px;flex-wrap:wrap;
  padding:10px 12px;border:1px solid var(--line,#e2e8f0);border-radius:10px;
}
.dp-hours.hs-strip .dp-hours-time{font-size:13.5px;font-weight:800;margin:0;font-variant-numeric:tabular-nums}
.dp-hours.hs-strip .dp-hours-days{font-size:12px;color:var(--ink-3,#64748b);margin:0}
.dp-hours.hs-strip .dp-hours-days::before{content:"· "}
.dp-hours.hs-strip .dp-hours-badge{margin:0 0 0 auto;font-size:10px;padding:3px 8px}
/* The note is the one thing allowed its own row, because it is a sentence. */
.dp-hours.hs-strip .dp-hours-note{flex:0 0 100%;margin:2px 0 0;font-size:11.5px}

/* ⚠ CSS BEATS THE PRESENTATION ATTRIBUTE.
   The rail icons ship `stroke="currentColor"`, but a stylesheet rule sets `stroke` on the svg
   itself, and CSS always wins over a presentation attribute. So on every design that puts the
   CTA on a solid accent tile, the glyph stayed accent-on-accent and vanished — the icons design
   showed an empty blue square with no way to tell what the button was. Hand the stroke back to
   currentColor, which those designs have already set to #fff. */
.dp-rail.rs-tiles .dp-rail-cta svg,
.dp-rail.rs-tiles .dp-rail-cta > i,
.dp-rail.rs-stack .dp-rail-cta svg,
.dp-rail.rs-icons .dp-rail-cta svg,
.dp-rail.rs-console .dp-rail-cta svg{stroke:currentColor;color:currentColor}

/* ══ PHASE_PORTAL_PAGER_WORDS — worded pager ══════════════════════════════════════════════
   The numbered pager's arrows were bare ‹ › glyphs. Worded, they need a wider hit area than a
   32px square, so the button sizes to its text instead of staying square. */
.pg-nums.pg-worded button[data-pg="prev"],
.pg-nums.pg-worded button[data-pg="next"]{
  width:auto;min-width:0;padding:0 12px;font-size:12.5px;font-weight:700;
}
/* PREVIOUS / NEXT ONLY — the fifth pagination design. */
.pg-pn{display:flex;align-items:center;justify-content:center;gap:14px;flex-wrap:wrap}
.pg-pn-b{
  padding:8px 15px;font:inherit;font-size:13px;font-weight:700;
  color:var(--ink,#0f172a);background:var(--card,#fff);
  border:1px solid var(--line,#e2e8f0);border-radius:var(--radius-sm,9px);cursor:pointer;
  transition:border-color .14s var(--ease,ease),color .14s var(--ease,ease);
}
.pg-pn-b:hover:not(:disabled){color:var(--accent);border-color:color-mix(in srgb,var(--accent) 45%,transparent)}
.pg-pn-b:focus-visible{outline:2px solid var(--accent);outline-offset:1px}
/* Disabled must still be READABLE — a customer on page 1 needs to see that "Previous" exists
   and is simply unavailable, so this dims rather than hides. */
.pg-pn-b:disabled{opacity:.45;cursor:default}
/* Tabular numerals so "Page 9 of 12" → "Page 10 of 12" does not shift the buttons sideways. */
.pg-pn-of{font-size:12.5px;color:var(--ink-3,#64748b);font-weight:600;font-variant-numeric:tabular-nums}
@media(max-width:480px){
  /* The counter drops to its own line rather than squeezing the two buttons. */
  .pg-pn{gap:9px}
  .pg-pn-of{order:3;flex:0 0 100%;text-align:center}
}

/* ══════════════════════════════════════════════════════════════════════════════════════════
   PHASE_PORTAL_SEARCH_PREMIUM — the request-list search field.

   Measured before: the field was 36px tall and the filter pills beside it 31px, with their
   vertical centres 6.5px apart, so the row read as two mismatched controls rather than one
   toolbar. Both now share ONE height token, and the toolbar centres them.
   ══════════════════════════════════════════════════════════════════════════════════════════ */
.rq-toolbar{
  --pxc-h:40px;              /* one height for every control on this row */
  align-items:center;
}
.rq-search{
  min-height:var(--pxc-h);
  padding:0 15px;                       /* height comes from min-height, not padding, so the
                                           field cannot drift when the font changes */
  border-radius:12px;
  gap:10px;
  /* A double background: a whisper-soft vertical gradient over the card colour reads as depth
     without tinting the field. Both derive from tokens, so it follows the operator's theme. */
  background:linear-gradient(180deg,color-mix(in srgb,var(--card) 96%,#000) 0%,var(--card) 62%);
  border:1px solid var(--line);
  /* Inset top highlight + a soft drop — the two together are what make an input read as
     "premium" rather than flat. Kept subtle enough to survive a dark theme. */
  box-shadow:inset 0 1px 0 rgba(255,255,255,.6), 0 1px 2px rgba(15,23,42,.04);
  transition:border-color .16s var(--ease,ease), box-shadow .16s var(--ease,ease), background .16s var(--ease,ease);
}
.rq-search:hover{border-color:color-mix(in srgb,var(--accent) 32%,var(--line))}
/* Focus lifts the field: accent border, a wider accent halo, and the inner highlight removed so
   it reads as pressed-in rather than raised. */
.rq-search:focus-within{
  border-color:var(--accent);
  background:var(--card);
  box-shadow:0 0 0 3px color-mix(in srgb,var(--accent) 14%,transparent),
             0 2px 10px -4px color-mix(in srgb,var(--accent) 40%,transparent);
}
.rq-search input{
  min-height:0;height:auto;line-height:1.2;   /* the wrapper owns the height */
  font-size:13.5px;font-weight:500;color:var(--ink);
}
.rq-search input::placeholder{color:var(--ink-3,#94a3b8);font-weight:400}
/* The magnifier tracks focus, so the eye is drawn to the active field. */
.rq-search svg{flex:none;color:var(--ink-3,#94a3b8);transition:color .16s var(--ease,ease)}
.rq-search:focus-within svg{color:var(--accent)}
/* The pills must match the field's height exactly, and centre their own text — padding alone
   left them 31px against the field's 36px. */
.rq-toolbar .reqfilters{display:flex;align-items:center;gap:8px;margin:0}
.rq-toolbar .reqfilters button{
  min-height:var(--pxc-h);
  display:inline-flex;align-items:center;justify-content:center;
  padding:0 16px;line-height:1;
}
@media(max-width:640px){
  /* Stacked, so the field takes the full width and the pills scroll rather than wrap raggedly. */
  .rq-search{width:100%}
  .rq-toolbar .reqfilters{overflow-x:auto;flex-wrap:nowrap;-webkit-overflow-scrolling:touch}
  .rq-toolbar .reqfilters button{flex:none}
}

/* ══════════════════════════════════════════════════════════════════════════════════════════
   PHASE_PORTAL_NAV_MOBILE_LANG — keep the language picker in the nav bar, beside the burger.

   THE CAUSE: at ≤760px the nav sets `.pnav-dd{width:100%}` so dropdowns become full-width
   accordions inside the drawer. The language trigger IS a .pnav-dd, so it inherited that width,
   could not fit beside the brand, and wrapped onto a second row — which grew the sticky nav to
   ~135px and left it covering the hero heading and half the search field.
   The picker lives in .px-navend, which is NOT a drawer item, so it must opt out.
   ══════════════════════════════════════════════════════════════════════════════════════════ */
@media(max-width:760px){
  /* Row order: brand · language · burger. The drawer keeps its flex-basis:100% and drops below.
     margin-left:auto is what pins the pair to the right without absolute positioning. */
  .pnav-in > .px-navend{order:1;margin-left:auto;width:auto;flex:0 0 auto;align-items:center}
  .pnav-in > .pnav-burger{order:2;margin-left:8px}
  .pnav-in > .pnav-items{order:3}
  /* Opt out of the drawer's full-width accordion sizing. */
  .px-navend .pnav-dd,
  .px-navend .px-util-lang{width:auto;flex:0 0 auto}
  /* Match the burger's 40px so the two sit level and the bar stays one row high. */
  .px-navend .px-lang .pnav-dd-btn{
    padding:0 8px;min-height:40px;font-size:12.5px;line-height:1;
    display:inline-flex;align-items:center;gap:6px;
  }
  .px-navend .px-lang .px-lang-code{font-size:12px}
  /* The account chip belongs in the drawer on mobile; only the language stays in the bar. */
  .px-navend > #px-acct{display:none}
  /* ⚠ THE MENU MUST STAY A FLOATING PANEL.
     The mobile rule above turns every .pnav-dd-menu into a static accordion with max-height:0.
     Inside the bar that means tapping ES opens nothing at all, so the picker is dead on a phone.
     Restore it as a right-anchored panel. */
  .px-navend .px-lang .pnav-dd-menu{
    position:absolute;top:calc(100% + 8px);right:0;left:auto;
    /* Same seven-row cap as the desktop panel (--pxl-cap is measured by pxLangCap), kept
       under a 60vh guard so a phone in landscape never gets a panel taller than its screen. */
    width:auto;min-width:190px;max-height:min(60vh,var(--pxl-cap,340px));
    overflow-y:auto;overflow-x:hidden;overscroll-behavior:contain;
    /* the bar itself is styled once, in portal-core.css, and is not width-scoped */
    padding:6px;border:1px solid var(--line);border-radius:12px;
    background:var(--card);
    box-shadow:0 18px 40px -14px rgba(15,23,42,.3);
    opacity:0;visibility:hidden;transform:translateY(-4px);
    transition:opacity .16s var(--ease,ease),transform .16s var(--ease,ease),visibility .16s;
  }
  .px-navend .px-lang.pnav-dd-open .pnav-dd-menu{opacity:1;visibility:visible;transform:none}
  .px-navend .px-lang .pnav-dd-menu .pdd-row{width:100%;padding:9px 10px;border-radius:8px}
}
@media(max-width:480px){
  /* Narrowest phones: drop the "ES" text and keep the flag, so brand + flag + burger still fit
     on one row rather than wrapping again. The label stays for screen readers. */
  .px-navend .px-lang .px-lang-code{
    position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%);
  }
  .px-navend .px-lang .pnav-dd-btn{padding:0 6px}
}

/* ══════════════════════════════════════════════════════════════════════════════════════════
   PHASE_PORTAL_MOBILE_RAIL_OVERLAP

   THE CAUSE, measured: .dp-rail is position:sticky. On desktop that is right — a short sidebar
   pinned beside long content. On a phone the grid collapses to ONE column, so the rail becomes a
   full-width 776px block ABOVE the content, and sticky pins it in place while the dashboard and
   the ticket list scroll underneath it. Measured overlap: 135px, the rail spanning 85→861 with
   the dashboard at 225→360 inside it.
   Sticky is meaningless once there is no column to sit beside, so it is dropped below the
   breakpoint. This is what actually stops the collision.
   ══════════════════════════════════════════════════════════════════════════════════════════ */
@media(max-width:760px){
  .dp-rail{position:static;top:auto}
}

/* ── The dashboard as its own card on mobile ───────────────────────────────────────────────
   Requested: same glassmorphism as everything else, but tinted blue and opaque enough to
   actually occlude rather than let the content beneath read through. The look pack's own tiles
   sit at 71% white, which is why they ghosted. */
@media(max-width:760px){
  #px-dashboard{
    padding:12px;border-radius:16px;
    /* Accent-tinted glass. The layered gradient keeps it reading as glass while the alpha floor
       is high enough to hide what is behind it — the point of the request. */
    background:
      linear-gradient(180deg,
        color-mix(in srgb,var(--accent) 16%, color-mix(in srgb,var(--card) 92%, transparent)) 0%,
        color-mix(in srgb,var(--accent) 9%,  color-mix(in srgb,var(--card) 96%, transparent)) 100%);
    -webkit-backdrop-filter:blur(18px) saturate(150%);
    backdrop-filter:blur(18px) saturate(150%);
    border:1px solid color-mix(in srgb,var(--accent) 22%,transparent);
    box-shadow:0 10px 30px -12px color-mix(in srgb,var(--accent) 30%,transparent),
               inset 0 1px 0 rgba(255,255,255,.5);
  }
  /* The tiles inside must be MORE opaque than the card, or the card's tint shows through them
     and the numbers lose contrast. !important because the glassmorphism look pack sets these
     backgrounds with !important. */
  #px-dashboard .pxd-tile{
    background:color-mix(in srgb,var(--card) 97%,transparent)!important;
    border-color:color-mix(in srgb,var(--accent) 18%,transparent);
  }
  /* The accent action card keeps its solid fill — it is the call to action. */
  #px-dashboard .pxd-action-card.primary{
    background:var(--accent)!important;border-color:var(--accent);
  }
}

/* ══ PHASE_PORTAL_SUBHERO_ALIGN ═══════════════════════════════════════════════════════════
   THE PAGE HEADER BAND IS ALWAYS LEFT-ALIGNED.

   I first centred the breadcrumb to match the heading — wrong way round. The breadcrumb has sat
   left on every page of this portal since it existed; it was the HEADING that had wandered.

   Why it wandered: .psh-row is a flex row holding the copy block and (when enabled) the search
   slot. On My requests the search IS in the band, so the copy is pushed left and the heading
   reads left. On the composer there is no search, the copy becomes the only child, and the
   band's inherited hero alignment (phero-center, from the arc design) centred it. So the
   heading's position depended on whether an unrelated setting happened to put a search field
   next to it — never a decision anyone made.

   The band is a PAGE HEADER, not a landing hero: it says where you are, so it aligns with the
   content beneath it. Scoped to #px-subhero, so the real landing hero keeps its own design
   alignment. */
#px-subhero .psh-row{justify-content:space-between}
#px-subhero .psh-copy{text-align:left}
#px-subhero .phero-h,
#px-subhero .phero-s{text-align:left}
#px-subhero .psh-crumb{justify-content:flex-start}
#px-subhero .psh-eyebrow{text-align:left}

/* ═══ FLOAT ANCHORS + ASSISTANT COMPOSER/LAUNCHER — moved to opsiq/assets/portal-assistant.css.
   The anchor rules position BOTH floating controls (.px-fab here, .pxa-launch on the Help
   Centre too), and /hc never loads this file — so they live with the assistant module that
   both surfaces load. Portal loads that file as well, so nothing here changes. ═══ */

/* The ticket reference above the band heading (view_heading = subject). Its own element rather
   than the greeting's eyebrow, so a portal using greeting_style='band' shows both. Colour is
   inherited from the heading at runtime, the same read-the-colour trick the breadcrumb uses —
   assuming light-on-dark breaks every light hero design. */
#px-subhero .psh-ref{
  font-size:12px;font-weight:800;letter-spacing:.08em;text-transform:uppercase;
  opacity:.72;margin-bottom:6px;
}

/* ══════════════════════════════════════════════════════════════════════════════════════════
   PHASE_PORTAL_REPLY_COMPOSER — more room to write, a button that is a button.

   Measured before: the reply field was 130px tall — about four lines — while "Send reply" was
   458px wide, because `.rowbtns button` carries `flex:1; min-width:130px` and there are only two
   buttons in that row. A half-width slab does not read as an action, it reads as a banner, and it
   drew more attention than the thing the customer is actually doing: writing.

   Scoped to `.composer` (the ticket reply) so the notification-preferences and rating rows, which
   share `.rowbtns` and DO want a full-width single button, are untouched.
   ══════════════════════════════════════════════════════════════════════════════════════════ */
#px-reply{
  min-height:200px;          /* was 130px — roughly four lines, now closer to seven */
  resize:vertical;           /* and the customer can take more if they need it */
}

.composer .rowbtns{
  justify-content:flex-end;  /* the primary action lands where the eye finishes reading */
  align-items:center;
  gap:10px;
}
.composer .rowbtns button{
  flex:0 0 auto;             /* the override that stops the slab */
  min-width:0;
  width:auto;
  padding:9px 18px;
  font-size:13px;
}
/* "Attach files" is secondary: it keeps the outline treatment and sits left of Send. */
.composer .rowbtns #px-attach{margin-right:auto}

@media (max-width:480px){
  /* On a phone a compact button in a corner is a small target, so let the pair share the row. */
  .composer .rowbtns{justify-content:stretch}
  .composer .rowbtns button{flex:1 1 auto;min-width:120px}
  .composer .rowbtns #px-attach{margin-right:0}
  #px-reply{min-height:160px}
}

/* ══════════════════════════════════════════════════════════════════════════════════════════
   PHASE_PORTAL_COMPOSE_PREVIEW_FS — preview and full screen, in the editor's own toolbar.

   Both composers (the new-request form and the ticket reply) build the same .rte toolbar, so the
   two controls live there rather than being bolted onto one page. Full screen previously existed
   for #p-message ONLY, which meant the reply box — the one place a customer is answering a long
   thread with the least room — never had it.
   ══════════════════════════════════════════════════════════════════════════════════════════ */
.rte-b.on{background:color-mix(in srgb,var(--accent) 16%,transparent);color:var(--accent)}

/* Preview reads like the posted message, because it IS the thread's renderer. */
.rte-preview{
  padding:12px 14px;font-size:14.5px;line-height:1.6;color:var(--ink);
  background:var(--card);border-top:1px solid var(--line-soft);
  overflow:auto;word-wrap:break-word;
}
.rte-preview[hidden]{display:none}
.rte-preview a{color:var(--accent);font-weight:600}
.rte-preview code{background:color-mix(in srgb,var(--ink) 7%,transparent);padding:1px 5px;border-radius:5px;font-size:.92em}
.rte-pv-empty{color:var(--ink-3);font-style:italic}

/* Full screen: the editor becomes the page. Fixed, so it escapes whatever card it sat in. */
.rte.rte-full{
  position:fixed;inset:0;z-index:210;margin:0;border-radius:0;
  display:flex;flex-direction:column;background:var(--card);
}
.rte.rte-full .rte-bar{flex:0 0 auto;border-radius:0}
.rte.rte-full textarea,
.rte.rte-full .rte-ce{flex:1 1 auto;min-height:0;height:auto;resize:none;border-radius:0}
.rte.rte-full .rte-preview{flex:1 1 auto;min-height:0}
/* The page behind must not scroll while the overlay is up. */
body.pxrte-full{overflow:hidden}

/* ══════════════════════════════════════════════════════════════════════════════════════════
   dl-single-column — REDESIGNED: THE CASE FILE. A premium information RAIL on the left, and the
   conversation as the page beside it.

   What it was: the two-column layout with its sidebar dropped underneath — status, ticket id, dates
   and "Mark resolved" sat BELOW the entire thread and the reply box, and the 280px cards stretched
   to 1280px became a ledger with ~1200px between each label and its value.

   What it is now, and why it is not just "sidebar-left":
     · The rail is not a stack of white cards. It is one continuous tinted column with hairline-
       separated tiles — a file spine rather than boxed widgets, which is what makes it read as its
       own design and not a repositioned copy of the other layouts.
     · It is STICKY. The facts stay with you through a long conversation; every other layout's
       sidebar scrolls away.
     · The thread gets a reading measure and real speech bubbles with tails (below), so the width
       goes to breathing room instead of line length.
   ══════════════════════════════════════════════════════════════════════════════════════════ */
#px-d-grid.dl-single-column{
  display:grid;
  grid-template-columns:312px minmax(0,1fr);
  gap:26px;
  align-items:start;
}

/* The case-file layout keeps its own COLUMN geometry; the sidebar's LOOK is now a separate
   setting (side_style), so any of the nine layouts can wear any of the five designs. */
/* the case-file layout's column geometry; STICKY is now a setting handled below for all layouts */

/* ── THE PAGE ─────────────────────────────────────────────────────────────────────────────── */
#px-d-grid.dl-single-column .rq-main{min-width:0}

@media (max-width:860px){
  /* Below a comfortable two-column width the rail goes back on top — still ABOVE the thread, never
     under the composer, which was the original sin of this layout. */
  #px-d-grid.dl-single-column{grid-template-columns:minmax(0,1fr);gap:18px}
  #px-d-grid.dl-single-column .rq-side{position:static}
}

/* ══════════════════════════════════════════════════════════════════════════════════════════
   dl-single-column — THE THREAD: real speech bubbles with tails, and no wasted space.

   Measured waste: every .brow carried `margin-bottom:28px` while the thread ALSO set `gap:14px`,
   so consecutive messages sat 42px apart; bubbles were padded 18px/20px; and 13.5px body text ran
   at a 24.3px line-height (1.8). Ten messages came to 2555px of scroll for a conversation you could
   read in a third of that.

   Now: one 16px rhythm, tighter padding, a 1.55 measure — and a TAIL, so a bubble reads as speech
   instead of a rounded panel. The support bubble is bordered, so its tail is two stacked triangles
   (the outer one border-coloured, the inner one card-coloured, offset by 1px) — a single triangle
   would show a flat edge where the border should continue.
   ══════════════════════════════════════════════════════════════════════════════════════════ */
.dl-single-column #px-d-thread{gap:16px}
.dl-single-column #px-d-thread .brow{margin:0;gap:11px;align-items:flex-end}

.dl-single-column #px-d-thread .bubble{
  position:relative;
  padding:11px 15px 9px;
  border-radius:16px;
  max-width:min(88%, 790px);
  box-shadow:0 1px 2px rgba(2,6,23,.04);
}
.dl-single-column #px-d-thread .bubble .who{
  font-size:10.5px;font-weight:800;letter-spacing:.07em;text-transform:uppercase;
  margin-bottom:2px;opacity:.72;
}
.dl-single-column #px-d-thread .bubble .body{font-size:14px;line-height:1.55}
/* The timestamp rides the bubble's last line instead of claiming a row of its own. */
.dl-single-column #px-d-thread .bubble .when,
.dl-single-column #px-d-thread .bubble time{
  display:block;margin-top:4px;font-size:11px;opacity:.6;
}

/* ── TAILS ─────────────────────────────────────────────────────────────────────────────────
   ⚠ A BORDER-TRIANGLE TAIL CANNOT MATCH A THEMED BUBBLE. The first attempt drew the tail with
   `border-color: var(--accent)`, which put a blue spike on a white bubble — and it would have been
   wrong again for every other bubble_style preset, since the customer bubble is accent-filled in
   some and light in others.

   A rotated square with `background:inherit; border:inherit` takes the bubble's OWN surface and
   OWN border, whatever the preset made them, so the tail is always the right colour by
   construction. Only the two outward edges keep their border, and the bubble's own background
   covers the join. */
/* ⚠ THE TAIL POINTS AT THE AVATAR, NOT AT THE FLOOR. The first version hung it off the BOTTOM edge
   (`bottom:-6px`, 18px in from a corner) pointing straight down — but the avatar sits to the SIDE of
   the bubble and near its TOP, so the tail pointed at nothing and read as a notch cut out of the
   underside. It now grows from the SIDE edge the avatar is on, at the avatar's own eye level, and it
   is longer so it actually reaches.

   ⚠ WHICH BORDERS SURVIVE DECIDES WHICH WAY IT POINTS. Under `rotate(45deg)` the square's original
   BOTTOM-LEFT corner ends up facing LEFT and its TOP-RIGHT corner faces RIGHT. So a left-pointing
   tail must keep border-left + border-bottom, and a right-pointing tail border-top + border-right.
   Dropping the wrong pair gives a spike with no outline on its visible edges. */
.dl-single-column #px-d-thread .bubble::after{
  content:'';position:absolute;z-index:-1;
  width:16px;height:16px;
  /* ⚠ ANCHOR TO THE BOTTOM, NOT THE TOP. The row is `align-items:flex-end`, so the avatar is
     BOTTOM-aligned and its centre sits 16px above the bubble's foot on every row no matter how tall
     the message is (measured: 16, 16, 16, 16 across bubbles of 85px to 249px). Anchoring the tail to
     the top aimed it correctly on short messages and hundreds of pixels high on long ones.
     16px up, less half the 17px tail, puts its point exactly on the avatar's centre line. */
  bottom:8px;top:auto;
  background:inherit;
  /* ⚠ DO NOT `border:inherit` HERE. The idea was that the tail would take whatever border the theme
     gave the bubble — but this bubble has a 3px ACCENT rule down its left edge, and inheriting it
     put a heavy blue spike beside the avatar instead of a hairline point. `inherit` also copies the
     four border colours separately, so the tail's two visible edges came out different colours.
     A single token hairline is predictable on every preset; the fill still inherits, so an
     accent-filled bubble keeps an accent-filled tail. */
  border:1px solid color-mix(in srgb,var(--ink) 12%,transparent);
  transform:rotate(45deg);
}
.dl-single-column #px-d-thread .bubble{isolation:isolate}   /* keeps z-index:-1 inside the bubble */

/* ── THE CUSTOMER'S BUBBLE ────────────────────────────────────────────────────────────────────
   It was measurably the same object as the support bubble — identical fill, identical 1px border,
   identical shadow — with the only difference being that SUPPORT got a 3px rule and a coloured
   name. So the customer's own words were the plainest thing on the page. It now carries a tinted
   fill of the operator's accent, a lit top edge, and a shadow that picks the accent up, so a glance
   down the thread separates the two voices without either shouting.

   ⚠ A FLAT FILL, NOT A GRADIENT. The tail is drawn with `background:inherit`, and an inherited
   gradient re-origins to the tail's own 16px box instead of continuing the bubble's — so the tail
   comes out a different shade and the join shows. A flat mix inherits exactly.

   ⚠ THE DEPTH IS ALL INSET OR OUTSET ON THE BUBBLE, NEVER A THICKER BORDER ON THE TAIL'S SIDE. The
   customer's tail leaves the RIGHT edge; a 3px rule there would be crossed by the tail's base, which
   is the same blue-spike defect the support tail had. Inset shadows do not reach the tail's box, so
   the tail stays a clean hairline. */
.dl-single-column #px-d-thread .brow.mine .bubble{
  /* !important because the glassmorphism look pack sets `.bubble{background:...!important}`; without
     it the tint silently lost and the customer's bubble stayed the same white as the desk's. */
  background:color-mix(in srgb,var(--accent) 8%,var(--card))!important;
  border-color:color-mix(in srgb,var(--accent) 30%,var(--line));
  box-shadow:
    inset 0 1px 0 color-mix(in srgb,var(--card) 85%,transparent),
    0 1px 2px color-mix(in srgb,var(--ink) 5%,transparent),
    0 8px 18px -12px color-mix(in srgb,var(--accent) 55%,transparent);
  transition:box-shadow .18s var(--ease,ease), border-color .18s var(--ease,ease);
}
/* the tail follows the bubble's own border, or it outlines in the wrong colour */
.dl-single-column #px-d-thread .brow.mine .bubble::after{
  border-color:color-mix(in srgb,var(--accent) 30%,var(--line));
}
/* The name is the customer's, so it takes the accent tempered with ink — related to the desk's
   accent name, not a copy of it. */
.dl-single-column #px-d-thread .brow.mine .who{
  color:color-mix(in srgb,var(--accent) 62%,var(--ink));
}
.dl-single-column #px-d-thread .brow.mine:hover .bubble{
  border-color:color-mix(in srgb,var(--accent) 48%,var(--line));
  box-shadow:
    inset 0 1px 0 color-mix(in srgb,var(--card) 92%,transparent),
    0 2px 4px color-mix(in srgb,var(--ink) 6%,transparent),
    0 12px 26px -12px color-mix(in srgb,var(--accent) 68%,transparent);
}
.dl-single-column #px-d-thread .brow.mine:hover .bubble::after{
  border-color:color-mix(in srgb,var(--accent) 48%,var(--line));
}
/* The customer's own plate answers the tint rather than staying the generic grey. */
.dl-single-column #px-d-thread .brow.mine .avat.cust{
  background:linear-gradient(color-mix(in srgb,var(--accent) 34%,var(--card)),
                             color-mix(in srgb,var(--accent) 52%,var(--card)));
  color:color-mix(in srgb,var(--ink) 78%,transparent);
}
/* SUPPORT — avatar on the left, so the tail leaves the LEFT edge pointing left. */
.dl-single-column #px-d-thread .bubble.support::after{
  /* ⚠ THE OFFSET IS NOT THE PROTRUSION. A square rotated 45deg reaches half its DIAGONAL past its
     own centre: 16px x 0.7071 = 11.31px. At left:-7px the centre sits 1px out and the point lands
     10.31px out — into a 10px gap, so it grazed the avatar. -5px puts the point 8.31px out and
     leaves a clean 1.7px. */
  left:-5px;right:auto;
  border-top-width:0;border-right-width:0;
  border-bottom-left-radius:3px;
}
/* CUSTOMER — avatar on the right, so the tail leaves the RIGHT edge pointing right. */
.dl-single-column #px-d-thread .bubble.mine::after{
  right:-5px;left:auto;
  border-bottom-width:0;border-left-width:0;
  border-top-right-radius:3px;
}
/* The corner the tail grows from loses its curve so it leaves a straight edge — that is now the TOP
   corner on the avatar's side, not the bottom one. */
.dl-single-column #px-d-thread .bubble.support{border-bottom-left-radius:6px}
.dl-single-column #px-d-thread .bubble.mine{border-bottom-right-radius:6px}

@media (max-width:860px){
  .dl-single-column #px-d-thread .bubble{max-width:92%}
}

/* ══════════════════════════════════════════════════════════════════════════════════════════
   PHASE_PORTAL_SIDE_STYLE — FIVE ticket-sidebar designs, independent of the nine layouts.

   The rail was built inside dl-single-column, which meant the best-looking sidebar was locked to
   one layout. Placement and dressing are now two separate decisions: dl-* positions the column,
   ds-* dresses it, so 9 × 5 combinations all work. Every design below styles ONLY the sidebar's
   own surfaces, so it never fights the layout that placed it.

     ds-cards   the classic boxed set (unchanged default)
     ds-rail    one continuous tinted spine — the case-file design
     ds-stack   borderless sections on hairlines, no card edges at all
     ds-glass   a frosted panel over the page
     ds-ledger  a compact tabular readout, for operators who want density
   ══════════════════════════════════════════════════════════════════════════════════════════ */

/* ── ds-rail — THE SPINE. Redesigned to be unmistakably its own thing. ────────────────────
   Rail and Cards had converged into the same design — measured side by side, both ended up with an
   8px radius, a 1px bottom border, a shadow and a gradient fill. That happened because Rail's
   identity was a tinted CONTAINER, and the container had to be abandoned: stretched to the
   conversation's height it left ~2200px of empty tinted box, and sized to its content it left the
   cards no room to pin. Rebuilt on a different idea entirely, one that needs no container:

     · A continuous ACCENT SPINE runs down the left edge. Each section paints its own 3px segment
       and the sections butt together, so the line is unbroken — and a section that ends up pinned
       alone still carries its own piece of it. No container, nothing to stretch.
     · NO cards. No shadows, no per-section rounding, no borders — sections are divided by
       hairlines and nothing else, so the column reads as one document rather than a stack.
     · A MARKER sits on the spine beside every section heading, like a timeline. That, more than any
       colour, is what makes this design legible at a glance next to Cards.
     · The tint fades left-to-right OUT of the spine, so the accent belongs to the edge rather than
       washing the whole panel.
   ══════════════════════════════════════════════════════════════════════════════════════════ */
#px-d-grid.ds-rail .rq-side{
  gap:0;background:transparent;border:0;box-shadow:none;
}
#px-d-grid.ds-rail .rq-side > .swrap{gap:0}

#px-d-grid.ds-rail .rq-side .side-card{
  position:relative;
  /* Opaque, so a pinned section never shows the thread through it. */
  background-color:var(--bg)!important;
  background-image:linear-gradient(90deg,
    color-mix(in srgb,var(--accent) 10%,var(--card)) 0,
    var(--card) 130px)!important;
  border:0!important;border-radius:0!important;box-shadow:none!important;
  margin:0!important;padding:16px 18px 16px 24px;
}
/* THE SPINE — one segment per section, butted into a single unbroken line. */
#px-d-grid.ds-rail .rq-side .side-card::before{
  content:'';position:absolute;left:0;top:0;bottom:0;width:3px;
  background:linear-gradient(180deg,
    var(--accent),
    color-mix(in srgb,var(--accent) 45%,transparent));
}
/* Sections are divided by a hairline and nothing else. */
#px-d-grid.ds-rail .rq-side .side-card + .side-card,
#px-d-grid.ds-rail .rq-side > .swrap > .side-card{
  border-top:1px solid color-mix(in srgb,var(--ink) 9%,transparent)!important;
}
/* Only the two ends of the whole column curve. */
#px-d-grid.ds-rail .rq-side > .side-card:first-child{border-radius:14px 14px 0 0!important;overflow:hidden}
#px-d-grid.ds-rail .rq-side > .swrap > .side-card:last-child{border-radius:0 0 14px 14px!important;overflow:hidden}
/* Pinned and left alone, the top section closes itself off — see PHASE_PORTAL_SIDE_ALONE. */
#px-d-grid.ds-rail .rq-side > .side-card:first-child.pxs-alone{border-radius:14px!important}

/* THE MARKER — a dot on the spine beside each heading. */
#px-d-grid.ds-rail .rq-side .sd-title,
#px-d-grid.ds-rail .rq-side .smc-h{position:relative}
#px-d-grid.ds-rail .rq-side .sd-title::before,
#px-d-grid.ds-rail .rq-side .smc-h::before{
  content:'';position:absolute;left:-24px;top:50%;translate:0 -50%;
  width:9px;height:9px;border-radius:50%;
  background:var(--accent);
  box-shadow:0 0 0 3px var(--card), 0 0 0 4.5px color-mix(in srgb,var(--accent) 30%,transparent);
}
/* The heading's icon chip goes flat — a raised chip fights the flat treatment. */
#px-d-grid.ds-rail .rq-side .sd-title .sd-title-ic{
  background:transparent;width:auto;height:auto;color:var(--accent);
}
/* ⚠ THE HEADING NEEDS TO OUTRANK THE LABELS. At 10.5px against 10px field labels it was the same
   size as the rows beneath it, so the card had a title that read as just another label and no
   hierarchy at all. The section heading is now clearly the largest thing in its own block. */
/* Uppercase stays — it is the portal's own heading language, and dropping it made these titles
   read as body text. The hierarchy comes from SIZE and colour instead: 12px against 9.5px labels. */
#px-d-grid.ds-rail .rq-side .sd-title,
#px-d-grid.ds-rail .rq-side .smc-h{
  font-size:12px;font-weight:800;letter-spacing:.09em;text-transform:uppercase;
  color:var(--ink);
  margin-bottom:13px;padding-bottom:0;border-bottom:0;
}

/* Facts: label left, value right, on dashed hairlines with tabular figures. */
#px-d-grid.ds-rail #px-d-fields{display:flex;flex-direction:column;gap:0}
#px-d-grid.ds-rail #px-d-fields .sd-row{
  display:flex;align-items:center;justify-content:space-between;gap:14px;padding:9px 0;border:0;
}
#px-d-grid.ds-rail #px-d-fields .sd-row + .sd-row{
  border-top:1px dashed color-mix(in srgb,var(--ink) 12%,transparent);
}
#px-d-grid.ds-rail #px-d-fields .sd-l{
  font-size:9.5px;font-weight:800;letter-spacing:.11em;text-transform:uppercase;
  color:var(--ink-3);white-space:nowrap;
}
#px-d-grid.ds-rail #px-d-fields .sd-v{
  font-size:13.5px;font-weight:700;text-align:right;font-variant-numeric:tabular-nums;
}
#px-d-grid.ds-rail .rq-side #px-d-actions{margin-top:14px}
#px-d-grid.ds-rail .rq-side #px-d-actions button{width:100%}
#px-d-grid.ds-rail .smc-item{padding-left:0}

/* ── ds-stack — THE PANEL. A real card, distinct by LAYOUT rather than by being flat. ─────
   Earlier attempts went the wrong way: "cards without rounding" (not a design), a spec-sheet gutter
   (needed width a 280px column does not have), and a surfaceless flat list (no card at all). This is
   a card like the others — its own surface, border and radius — and what makes it different is the
   inside: a titled header strip, then the facts as a 2-UP GRID OF TILES with the label above the
   value, where designs 1 and 2 both run label-left / value-right rows. All colour from tokens. */
#px-d-grid.ds-stack .rq-side{display:flex;flex-direction:column;gap:14px;background:transparent}
#px-d-grid.ds-stack .rq-side > .swrap{display:flex;flex-direction:column;gap:14px}

#px-d-grid.ds-stack .rq-side .side-card{
  background:var(--card)!important;
  border:1px solid var(--line)!important;
  border-radius:14px!important;
  /* Same four-layer depth as the reading card beside it, derived from --ink so it follows the palette. */
  box-shadow:
    0 1px 2px color-mix(in srgb,var(--ink) 5%,transparent),
    0 1px 3px color-mix(in srgb,var(--ink) 6%,transparent),
    0 4px 6px -1px color-mix(in srgb,var(--ink) 5%,transparent),
    0 10px 24px -6px color-mix(in srgb,var(--ink) 10%,transparent)!important;
  margin:0!important;padding:0!important;
  overflow:hidden;
}
/* HEADER STRIP — the title gets its own tinted band inside the card. */
#px-d-grid.ds-stack .rq-side .sd-title,
#px-d-grid.ds-stack .rq-side .smc-h{
  display:flex;align-items:center;gap:9px;margin:0;
  padding:12px 14px;
  background:linear-gradient(180deg,color-mix(in srgb,var(--accent) 8%,var(--card)),var(--card));
  border-bottom:1px solid var(--line);
  font-weight:800;letter-spacing:.12em;text-transform:uppercase;
  color:color-mix(in srgb,var(--ink) 62%,transparent);
}
/* Every section heading matches — same size, tracking, colour and padding as the ticket card's own,
   so the four cards read as one set instead of one primary and three smaller ones. */
#px-d-grid.ds-stack .rq-side > .side-card .sd-title,
#px-d-grid.ds-stack .rq-side .smc-h{
  font-size:12.5px;letter-spacing:.1em;
  color:var(--ink);
  padding:14px;
}
#px-d-grid.ds-stack .rq-side .sd-title .sd-title-ic{
  width:22px;height:22px;border-radius:6px;
  background:color-mix(in srgb,var(--accent) 14%,transparent);color:var(--accent);
}
#px-d-grid.ds-stack .rq-side .sd-title .sd-title-ic svg{width:13px;height:13px}

/* THE 2-UP TILE GRID — the part no other design does. Hairlines are the gaps. */
/* ONE FACT PER ROW, all of them in the table. Two facts sharing a row packed the label and value
   of each into a half-width cell, which is what made it read as tiles rather than as a table — and
   forced Status and Priority into ragged full-width exceptions. Single column: label left, value
   right, a hairline between every row. The table treatment (ruled cells, header band) is what keeps
   this distinct from design 1's plain rows. */
#px-d-grid.ds-stack #px-d-fields{
  display:grid;grid-template-columns:1fr;gap:1px;
  background:var(--line);
  border-bottom:1px solid var(--line);
}
/* Each row is a two-cell table row: label | value, with a CENTRE RULE between them. The padding
   moves onto the cells so the vertical line runs the full height of the row and lines up from row to
   row, giving a continuous column divider rather than six separate dashes. */
#px-d-grid.ds-stack #px-d-fields .sd-row{
  display:grid;grid-template-columns:1fr 1fr;align-items:center;gap:0;
  padding:0!important;border:0!important;background:var(--card);
}
/* ⚠ THE RULE CANNOT LIVE ON THE VALUE ELEMENT. There is no cell wrapper — the value's direct child
   IS the pill on the status row — so `border-left` + cell padding landed on the pill itself: the
   line became the pill's own left edge (invisible against its fill), the pill stretched the full
   cell, and the cell's text-align pushed its label to the right. The rule is drawn on the ROW as a
   pseudo-element at the 50% line instead, so it is independent of whatever the value happens to be,
   and the values are inset with MARGIN so a pill keeps its own shape. */
#px-d-grid.ds-stack #px-d-fields .sd-row{position:relative}
#px-d-grid.ds-stack #px-d-fields .sd-row::after{
  content:'';position:absolute;left:50%;top:0;bottom:0;width:1px;
  background:color-mix(in srgb,var(--ink) 11%,transparent);
  pointer-events:none;
}
#px-d-grid.ds-stack #px-d-fields .sd-row > .sd-l{padding:10px 12px}
#px-d-grid.ds-stack #px-d-fields .sd-row > *:not(.sd-l){
  margin:9px 12px;justify-self:end;min-width:0;
  text-align:right;
}
/* a pill must not be stretched or re-aligned inside — it carries its own padding and centring */
#px-d-grid.ds-stack #px-d-fields .sd-row > .pill,
#px-d-grid.ds-stack #px-d-fields .sd-row > .prio-tag{text-align:center;justify-self:end}
/* ⚠ THE DEMARCATION HAS TO BE A REAL BORDER. Relying on `gap:1px` over the container's background
   to draw the rules left them invisible — the gap renders, but --line at 1px behind an opaque row is
   too faint to read as a table. An explicit rule per row is unambiguous, and it needs !important
   because the rule above zeroes the row's borders. */
#px-d-grid.ds-stack #px-d-fields .sd-row + .sd-row{
  border-top:1px solid color-mix(in srgb,var(--ink) 11%,transparent)!important;
}
/* single column, so nothing needs to span and there is no orphan cell */
/* the pill and the priority dot have to sit inside a half-width cell without overflowing */
#px-d-grid.ds-stack #px-d-fields .sd-row .pill,
#px-d-grid.ds-stack #px-d-fields .sd-row .prio-tag{
  max-width:100%;font-size:9.5px;padding:5px 9px;white-space:nowrap;
  overflow:hidden;text-overflow:ellipsis;
}
#px-d-grid.ds-stack #px-d-fields .sd-l{
  font-size:9.5px;font-weight:800;letter-spacing:.11em;text-transform:uppercase;
  color:var(--ink-3);white-space:nowrap;flex:0 0 auto;
}
#px-d-grid.ds-stack #px-d-fields .sd-v{
  font-size:12.5px;font-weight:700;text-align:right;
  font-variant-numeric:tabular-nums;color:var(--ink);
}
/* The action is the table's LAST ROW, not something floating under it: same 12px cell padding as
   every other cell and the same rule above it, so the demarcation carries all the way down and the
   button sits inside the cell rather than bleeding to the card's edges. */
#px-d-grid.ds-stack .rq-side #px-d-actions{
  margin:0;padding:12px;
  border-top:1px solid color-mix(in srgb,var(--ink) 11%,transparent);
  background:var(--card);
}
#px-d-grid.ds-stack .rq-side #px-d-actions button{width:100%;margin:0}
/* the fields table no longer needs its own closing line — the action row's top rule is that line */
#px-d-grid.ds-stack #px-d-fields{border-bottom:0}

/* Body sections: padded list, hairline between rows, accent on hover. */
#px-d-grid.ds-stack .rq-side .smc-item{
  padding:9px 14px;border-radius:0;background:transparent;
  transition:background .15s var(--ease,ease),color .15s var(--ease,ease);
}
#px-d-grid.ds-stack .rq-side .smc-item + .smc-item{border-top:1px solid color-mix(in srgb,var(--ink) 7%,transparent)}
#px-d-grid.ds-stack .rq-side .smc-item:hover{background:color-mix(in srgb,var(--accent) 7%,transparent);color:var(--accent)}
#px-d-grid.ds-stack .rq-side .smc-empty{padding:11px 14px}

@media(max-width:480px){
  #px-d-grid.ds-stack #px-d-fields{grid-template-columns:1fr}
  #px-d-grid.ds-stack #px-d-fields .sd-row:first-child{grid-column:1}
}

/* ── ds-glass — THE FROSTED TICKET STUB ───────────────────────────────────────────────────
   ⚠ TWO EARLIER ATTEMPTS WERE REJECTED AS "not different, nothing changes", and both deserved it:
   clear frost (invisible on a near-white page), then a tint plus rounded chips — which is still a
   label/value row list, i.e. Stack with softer edges. A restyle is not a design.
   So this one changes the STRUCTURE. It is a support ticket, so it is shaped like a ticket stub:
   a header stub carrying the reference in mono, a PERFORATION with real notches bitten out of both
   edges, and the facts below it as torn-off rows on dashed tear lines. Nothing else in the set has a
   dashed line, a notch, or mono type — the identity is in the construction, not the colour.

   Every colour is mixed from --accent / --card / --ink / --line / --bg. No literals; asserted.

   ⚠ NO `overflow` ON THE PANE, twice over. It would clip the notches off, and it also makes the pane
   the SCROLLPORT for any sticky descendant — `top:82px` stops meaning "below the nav" and starts
   meaning "below the top of the pane", which parked the card there permanently (measured: an 83px
   band of empty frost above the heading).
   ⚠ THE RESETS ARE !important — the glassmorphism look pack sets `.card{background:…!important;
   box-shadow:…!important}` and a plain reset loses.
   ⚠ BOTH STICKY-MODE CLASSES ARE NAMED on every override, or a one-id-two-class rule ties with the
   generic `.dss-sticky.dss-tall` and loses on source order. */
#px-d-grid.ds-glass .rq-side{
  display:flex;flex-direction:column;gap:0;
  border-radius:18px;
  position:relative;
  background:
    linear-gradient(168deg,
      color-mix(in srgb,var(--accent) 14%,var(--card)) 0%,
      color-mix(in srgb,var(--accent) 4%,var(--card)) 52%,
      color-mix(in srgb,var(--card) 94%,var(--ink)) 100%);
  border:1px solid color-mix(in srgb,var(--accent) 20%,var(--line));
  /* the reading card's own four layers, from --ink, plus the two inset edges that read as glass */
  box-shadow:
    0 1px 2px color-mix(in srgb,var(--ink) 5%,transparent),
    0 1px 3px color-mix(in srgb,var(--ink) 6%,transparent),
    0 4px 6px -1px color-mix(in srgb,var(--ink) 5%,transparent),
    0 10px 24px -6px color-mix(in srgb,var(--ink) 10%,transparent),
    inset 0 1px 0 color-mix(in srgb,var(--card) 92%,transparent),
    inset 0 -1px 0 color-mix(in srgb,var(--ink) 7%,transparent);
}
@supports (backdrop-filter:blur(1px)){
  #px-d-grid.ds-glass .rq-side{backdrop-filter:blur(20px) saturate(1.45)}
}

/* ── THE HEADER STUB ── its own tinted zone, closed by a perforation. */
#px-d-grid.ds-glass .rq-side .side-card{
  background-color:transparent!important;
  background-image:none!important;
  border:0!important;border-radius:0!important;box-shadow:none!important;
  margin:0!important;padding:16px 18px 17px!important;
  backdrop-filter:none!important;
  position:relative;
}
#px-d-grid.ds-glass .rq-side > .side-card:first-child{
  border-radius:18px 18px 0 0!important;
  padding-bottom:19px!important;
  background-image:radial-gradient(130% 100% at 8% -20%,
    color-mix(in srgb,var(--accent) 22%,transparent), transparent 60%)!important;
}

/* ── THE PERFORATION ── a dashed tear line between every section. */
#px-d-grid.ds-glass .rq-side .side-card + .side-card,
#px-d-grid.ds-glass .rq-side > .swrap,
#px-d-grid.ds-glass .rq-side > .swrap > .side-card + .side-card{
  border-top:1px dashed color-mix(in srgb,var(--ink) 22%,transparent)!important;
}
/* ── THE NOTCHES ── bitten out of both edges at the first tear, which is what makes it a stub and
   not a panel. Filled with the PAGE colour so they read as holes, not as dots. */
#px-d-grid.ds-glass .rq-side > .swrap::before,
#px-d-grid.ds-glass .rq-side > .swrap::after{
  content:'';position:absolute;top:-9px;width:17px;height:17px;border-radius:50%;
  background:var(--bg);
  border:1px solid color-mix(in srgb,var(--accent) 20%,var(--line));
  z-index:2;
}
#px-d-grid.ds-glass .rq-side > .swrap::before{left:-9px}
#px-d-grid.ds-glass .rq-side > .swrap::after{right:-9px}
#px-d-grid.ds-glass .rq-side > .swrap{position:relative}

#px-d-grid.dss-sticky.dss-tall.ds-glass .rq-side > .swrap,
#px-d-grid.dss-sticky.dss-fits.ds-glass .rq-side > .swrap{
  display:flex;flex-direction:column;gap:0!important;margin:0!important;position:relative!important;
}
#px-d-grid.dss-sticky.dss-tall.ds-glass .rq-side > .swrap > .side-card,
#px-d-grid.dss-sticky.dss-fits.ds-glass .rq-side > .swrap > .side-card{margin:0!important}

/* ── THE PANE IS THE STICKY UNIT ──────────────────────────────────────────────────────────────
   ⚠ THE SECTIONS HERE ARE TRANSPARENT, SO THEY CANNOT PASS IN FRONT OF ANYTHING. The generic tall
   mode pins the ticket card and sends the sections over it — right for the four designs whose
   sections are opaque cards, but here it drew every section on top of the pinned one AT ONCE:
   "TICKET INFORMATION" through "I'm having issue with my domain", labels through values, illegible.
   One stub has nothing to slide over itself: the PANE holds and the sections stay put.
   ⚠ align-self:start IS LOAD-BEARING — without it the pane inherits stretch and hangs below its own
   last section as a giant empty tinted box. */
#px-d-grid.dss-sticky.dss-tall.ds-glass .rq-side,
#px-d-grid.dss-sticky.dss-fits.ds-glass .rq-side{
  position:sticky!important;
  top:calc(var(--px-navh,0px) + 14px)!important;
  align-self:start!important;
}
#px-d-grid.dss-sticky.dss-tall.ds-glass .rq-side .side-card,
#px-d-grid.dss-sticky.dss-fits.ds-glass .rq-side .side-card{
  position:relative!important;top:auto!important;z-index:auto!important;
}

/* ── THE HEADINGS ── small, wide-tracked, with a mono hash. Not a band, not a border. */
#px-d-grid.ds-glass .rq-side .sd-title,
#px-d-grid.ds-glass .rq-side .smc-h{
  margin:0 0 14px;padding:0;border:0;
  color:color-mix(in srgb,var(--ink) 55%,transparent);
  font-size:9.5px;letter-spacing:.2em;
}
#px-d-grid.ds-glass .rq-side .sd-title{
  font-size:10px;color:color-mix(in srgb,var(--ink) 72%,transparent);
}

/* ── THE FACTS ── torn rows on tear lines. One fact per row, label left, value right in mono
   tabular figures, which is what a printed stub looks like and what nothing else here does. */
#px-d-grid.ds-glass #px-d-fields{
  display:flex;flex-direction:column;gap:0;background:none;border:0;
}
#px-d-grid.ds-glass #px-d-fields .sd-row{
  display:grid;grid-template-columns:auto 1fr;align-items:center;gap:10px;
  padding:10px 0!important;border:0!important;background:none!important;
}
#px-d-grid.ds-glass #px-d-fields .sd-row + .sd-row{
  border-top:1px dashed color-mix(in srgb,var(--ink) 16%,transparent)!important;
}
#px-d-grid.ds-glass #px-d-fields .sd-row > .sd-l{
  font-size:9px;letter-spacing:.16em;
  color:color-mix(in srgb,var(--ink) 48%,transparent);
}
#px-d-grid.ds-glass #px-d-fields .sd-row > *:not(.sd-l){
  justify-self:end;text-align:right;min-width:0;
  font-family:ui-monospace,Menlo,Consolas,monospace;
  font-size:12px;font-weight:700;letter-spacing:-.01em;
  font-variant-numeric:tabular-nums;
  color:color-mix(in srgb,var(--ink) 92%,transparent);
}
#px-d-grid.ds-glass #px-d-fields .sd-row > .pill,
#px-d-grid.ds-glass #px-d-fields .sd-row > .prio-tag{
  text-align:center;font-family:inherit;
}
#px-d-grid.ds-glass .rq-side #px-d-actions{margin:15px 0 0;padding:0}
/* width is the operator's `Action button width` setting -- not ours to force here */

/* ── THE LISTS ── tear lines again, and a mono reference under each title. */
#px-d-grid.ds-glass .rq-side .smc-item{
  border:0!important;border-radius:0!important;margin:0!important;
  padding:11px 0!important;background:none!important;
  transition:padding-left .18s var(--ease,ease), color .18s var(--ease,ease);
}
#px-d-grid.ds-glass .rq-side .smc-item + .smc-item{
  border-top:1px dashed color-mix(in srgb,var(--ink) 14%,transparent)!important;
}
#px-d-grid.ds-glass .rq-side .smc-item:hover{
  padding-left:7px!important;
  color:var(--accent)!important;
}

/* ── ds-slab — TINTED GLASS, FACTS ON FLOATING CHIPS ──────────────────────────────────────
   The sixth design, and a sibling to ds-glass rather than a replacement for it: Glass is a frosted
   ticket STUB built from perforations and tears, this is a tinted SLAB with the facts on chips that
   float above it. Both are glassmorphism; they differ in how the information is carried.

   Set against the rest: Cards is a boxed set, Rail is a tinted spine, Stack is a ruled table, Ledger
   is a dense readout. Here nothing is ruled or bordered — space, tint and cast shadow do the work.

   Every colour is mixed from --accent / --card / --ink / --line, so the design follows the configured
   palette in light or dark. No literals; asserted by the build.

   ⚠ NO `overflow` ON THE PANE — it makes the pane the SCROLLPORT for its own sticky child, which
   turns `top:82px` from "below the nav" into "below the top of the pane" and parks it there (measured
   on ds-glass as an 83px band of empty frost above the heading). First/last sections carry the radius.
   ⚠ THE RESETS ARE !important — the glassmorphism look pack sets `.card{background:…!important;
   box-shadow:…!important}` and a plain reset loses, leaving a drop shadow on every section.
   ⚠ BOTH STICKY-MODE CLASSES ARE NAMED on the overrides, or a one-id-two-class rule ties with the
   generic `.dss-sticky.dss-tall` and loses on source order — which reimposes gap/margin and tears
   the slab into separate pieces. */
#px-d-grid.ds-slab .rq-side{
  display:flex;flex-direction:column;gap:0;
  border-radius:20px;
  background:
    linear-gradient(160deg,
      color-mix(in srgb,var(--accent) 13%,var(--card)) 0%,
      color-mix(in srgb,var(--accent) 5%,var(--card)) 46%,
      color-mix(in srgb,var(--card) 92%,var(--ink)) 100%);
  border:1px solid color-mix(in srgb,var(--accent) 18%,var(--line));
  /* the reading card's own four layers, from --ink, plus two inset edges for the glass lip */
  box-shadow:
    0 1px 2px color-mix(in srgb,var(--ink) 5%,transparent),
    0 1px 3px color-mix(in srgb,var(--ink) 6%,transparent),
    0 4px 6px -1px color-mix(in srgb,var(--ink) 5%,transparent),
    0 10px 24px -6px color-mix(in srgb,var(--ink) 10%,transparent),
    inset 0 1px 0 color-mix(in srgb,var(--card) 92%,transparent),
    inset 0 -1px 0 color-mix(in srgb,var(--ink) 7%,transparent);
}
@supports (backdrop-filter:blur(1px)){
  #px-d-grid.ds-slab .rq-side{backdrop-filter:blur(20px) saturate(1.45)}
}
#px-d-grid.ds-slab .rq-side .side-card{
  background-color:transparent!important;
  background-image:none!important;
  border:0!important;border-radius:0!important;box-shadow:none!important;
  margin:0!important;padding:16px 16px 18px!important;
  backdrop-filter:none!important;
}
#px-d-grid.ds-slab .rq-side > .side-card:first-child{border-radius:20px 20px 0 0!important}
#px-d-grid.ds-slab .rq-side > .swrap > .side-card:last-child{border-radius:0 0 20px 20px!important}
/* a light seam over a dark one, the way a real join in glass catches the light */
#px-d-grid.ds-slab .rq-side .side-card + .side-card,
#px-d-grid.ds-slab .rq-side > .swrap,
#px-d-grid.ds-slab .rq-side > .swrap > .side-card + .side-card{
  border-top:1px solid color-mix(in srgb,var(--ink) 9%,transparent)!important;
  box-shadow:inset 0 1px 0 color-mix(in srgb,var(--card) 80%,transparent)!important;
}
#px-d-grid.dss-sticky.dss-tall.ds-slab .rq-side > .swrap,
#px-d-grid.dss-sticky.dss-fits.ds-slab .rq-side > .swrap{
  display:flex;flex-direction:column;gap:0!important;margin:0!important;
}
#px-d-grid.dss-sticky.dss-tall.ds-slab .rq-side > .swrap > .side-card,
#px-d-grid.dss-sticky.dss-fits.ds-slab .rq-side > .swrap > .side-card{margin:0!important}

/* ── THE PANE IS THE STICKY UNIT ──────────────────────────────────────────────────────────────
   ⚠ THE SECTIONS HERE ARE TRANSPARENT, SO THEY CANNOT PASS IN FRONT OF ANYTHING. Generic tall mode
   pins the ticket card and sends the sections over it — correct for the designs whose sections are
   opaque cards, but here it drew every section on top of the pinned one at once and the slab was
   illegible. One sheet of glass has nothing to slide over itself: the PANE holds, the sections stay.
   ⚠ align-self:start IS LOAD-BEARING, or the pane stretches to the grid height and hangs below its
   own last section as a giant empty tinted box. */
#px-d-grid.dss-sticky.dss-tall.ds-slab .rq-side,
#px-d-grid.dss-sticky.dss-fits.ds-slab .rq-side{
  position:sticky!important;
  top:calc(var(--px-navh,0px) + 14px)!important;
  align-self:start!important;
}
#px-d-grid.dss-sticky.dss-tall.ds-slab .rq-side .side-card,
#px-d-grid.dss-sticky.dss-fits.ds-slab .rq-side .side-card{
  position:static!important;top:auto!important;z-index:auto!important;
}
#px-d-grid.dss-sticky.dss-tall.ds-slab .rq-side > .swrap,
#px-d-grid.dss-sticky.dss-fits.ds-slab .rq-side > .swrap{
  position:static!important;z-index:auto!important;
}

/* ── THE HEADINGS — etched into the glass, with an accent tick. */
#px-d-grid.ds-slab .rq-side .sd-title,
#px-d-grid.ds-slab .rq-side .smc-h{
  margin:0 0 13px;padding:0 0 0 11px;border:0;position:relative;
  color:color-mix(in srgb,var(--ink) 82%,transparent);
}
#px-d-grid.ds-slab .rq-side .sd-title::before,
#px-d-grid.ds-slab .rq-side .smc-h::before{
  content:'';position:absolute;left:0;top:50%;translate:0 -50%;
  width:3px;height:13px;border-radius:2px;
  background:linear-gradient(var(--accent),color-mix(in srgb,var(--accent) 45%,transparent));
}

/* ── THE CHIPS — one fact per chip, floating on the slab. A bright top edge and a cast shadow put
   each chip ABOVE the glass rather than in it. */
#px-d-grid.ds-slab #px-d-fields{
  display:flex;flex-direction:column;gap:7px;background:none;border:0;
}
#px-d-grid.ds-slab #px-d-fields .sd-row{
  display:grid;grid-template-columns:auto 1fr;align-items:center;gap:10px;
  padding:9px 12px!important;border:0!important;border-radius:11px;
  background:color-mix(in srgb,var(--card) 62%,transparent)!important;
  box-shadow:
    inset 0 1px 0 color-mix(in srgb,var(--card) 96%,transparent),
    0 1px 2px color-mix(in srgb,var(--ink) 6%,transparent),
    0 3px 8px -4px color-mix(in srgb,var(--ink) 12%,transparent);
  transition:background .18s var(--ease,ease), box-shadow .18s var(--ease,ease);
}
#px-d-grid.ds-slab #px-d-fields .sd-row:hover{
  background:color-mix(in srgb,var(--card) 84%,transparent)!important;
  box-shadow:
    inset 0 1px 0 color-mix(in srgb,var(--card) 98%,transparent),
    0 2px 4px color-mix(in srgb,var(--ink) 7%,transparent),
    0 8px 18px -6px color-mix(in srgb,var(--accent) 26%,transparent);
}
#px-d-grid.ds-slab #px-d-fields .sd-row > .sd-l{
  font-size:9.5px;letter-spacing:.12em;
  color:color-mix(in srgb,var(--ink) 55%,transparent);
}
#px-d-grid.ds-slab #px-d-fields .sd-row > *:not(.sd-l){
  justify-self:end;text-align:right;min-width:0;
  font-size:12.5px;font-weight:700;font-variant-numeric:tabular-nums;
}
#px-d-grid.ds-slab #px-d-fields .sd-row > .pill,
#px-d-grid.ds-slab #px-d-fields .sd-row > .prio-tag{text-align:center}

/* ── MARK RESOLVED — its own button here. Everywhere else it is a solid accent slab, which on glass
   reads as a foreign object dropped onto the pane. This one is a GLASS button: the accent showing
   through a frosted face, a specular top lip, and an accent bloom on hover. All from tokens. */
#px-d-grid.ds-slab .rq-side #px-d-actions{margin:14px 0 0;padding:0}
/* ⚠ SCOPED TO `.abl-gradient`, THE DEFAULT LOOK, AND IT DOES NOT TOUCH WIDTH. Written unscoped with
   !important, this glass treatment beat the operator's own Action-button settings: picking any of the
   six looks (solid / soft / outline / glow / ghost) or a narrower width did nothing, because the
   design's rule outranked `.sd-actions.abl-*`. Measured: shape still worked, look and width were
   dead. The signature glass button is what you get on the DEFAULT look; choose another and the
   normal treatment comes through, which is what respecting the configuration means. */
#px-d-grid.ds-slab .rq-side #px-d-actions.abl-gradient button{
  background:linear-gradient(
    color-mix(in srgb,var(--accent) 82%,transparent),
    color-mix(in srgb,var(--accent) 96%,var(--ink)))!important;
  border:1px solid color-mix(in srgb,var(--card) 34%,var(--accent))!important;
  color:var(--card)!important;
  box-shadow:
    inset 0 1px 0 color-mix(in srgb,var(--card) 52%,transparent),
    inset 0 -1px 0 color-mix(in srgb,var(--ink) 16%,transparent),
    0 2px 5px color-mix(in srgb,var(--accent) 22%,transparent),
    0 10px 22px -10px color-mix(in srgb,var(--accent) 55%,transparent)!important;
  backdrop-filter:blur(6px);
  transition:box-shadow .2s var(--ease,ease), translate .2s var(--ease,ease);
}
#px-d-grid.ds-slab .rq-side #px-d-actions.abl-gradient button:hover{
  translate:0 -1px;
  box-shadow:
    inset 0 1px 0 color-mix(in srgb,var(--card) 62%,transparent),
    inset 0 -1px 0 color-mix(in srgb,var(--ink) 18%,transparent),
    0 3px 7px color-mix(in srgb,var(--accent) 26%,transparent),
    0 16px 30px -12px color-mix(in srgb,var(--accent) 70%,transparent)!important;
}
#px-d-grid.ds-slab .rq-side #px-d-actions.abl-gradient button:active{translate:0 0}

/* The link lists share the chip language so the whole slab reads as one design. */
#px-d-grid.ds-slab .rq-side .smc-item{
  border:0!important;border-radius:11px;margin-bottom:6px;padding:9px 12px!important;
  background:color-mix(in srgb,var(--card) 52%,transparent)!important;
  box-shadow:inset 0 1px 0 color-mix(in srgb,var(--card) 92%,transparent);
  transition:background .18s var(--ease,ease), translate .18s var(--ease,ease);
}
#px-d-grid.ds-slab .rq-side .smc-item:hover{
  background:color-mix(in srgb,var(--card) 82%,transparent)!important;
  translate:0 -1px;
}

/* ── ds-ledger — density. Zebra rows, tabular figures, tight leading: a readout for operators who
   would rather see everything at once than have it spaced out. */
#px-d-grid.ds-ledger .rq-side{display:flex;flex-direction:column;gap:12px}
#px-d-grid.ds-ledger .rq-side .side-card{
  border-radius:10px;padding:0;overflow:hidden;
  border:1px solid var(--line);
  /* SAME DEPTH AS THE READING CARD beside it — the identical four-layer stack, derived from --ink so
     it follows the palette. It was `box-shadow:none`, which left the cards sitting flat on the page
     next to a reading card that has real lift. !important because the glassmorphism look pack sets
     `.card{box-shadow:…!important}` and a plain declaration loses to it. */
  box-shadow:
    0 1px 2px color-mix(in srgb,var(--ink) 5%,transparent),
    0 1px 3px color-mix(in srgb,var(--ink) 6%,transparent),
    0 4px 6px -1px color-mix(in srgb,var(--ink) 5%,transparent),
    0 10px 24px -6px color-mix(in srgb,var(--ink) 10%,transparent)!important;
}
#px-d-grid.ds-ledger .smc-h,
#px-d-grid.ds-ledger .side-card > .sd-h{
  padding:9px 12px;margin:0;
  background:color-mix(in srgb,var(--ink) 4%,transparent);
  border-bottom:1px solid var(--line);
  font-size:10px;letter-spacing:.11em;text-transform:uppercase;
}
#px-d-grid.ds-ledger #px-d-fields{display:flex;flex-direction:column;gap:0}
#px-d-grid.ds-ledger #px-d-fields .sd-row{
  display:flex;align-items:center;justify-content:space-between;gap:10px;
  padding:6px 12px;border:0;font-size:12.5px;
}
#px-d-grid.ds-ledger #px-d-fields .sd-row:nth-child(odd){background:color-mix(in srgb,var(--ink) 3%,transparent)}
#px-d-grid.ds-ledger #px-d-fields .sd-l{font-size:10px;letter-spacing:.08em;text-transform:uppercase;color:var(--ink-3)}
#px-d-grid.ds-ledger #px-d-fields .sd-v{font-size:12.5px;font-weight:700;font-variant-numeric:tabular-nums}
#px-d-grid.ds-ledger .rq-side #px-d-actions{padding:10px 12px;margin:0}
/* width is the operator's `Action button width` setting -- not ours to force here */
#px-d-grid.ds-ledger .smc-item{padding:7px 12px;font-size:12.5px}

/* ══════════════════════════════════════════════════════════════════════════════════════════
   PHASE_PORTAL_SIDE_POS_STICKY — the info column's SIDE and its STICKINESS, for every layout.

   Left-or-right used to be a property of the LAYOUT: you got it by choosing `sidebar-left` instead
   of `sidebar-right`, which meant picking a side also picked everything else about the layout. It
   is its own decision now (dsp-left / dsp-right), so any of the nine layouts × five designs can
   put the column on either side. The width stays whatever the layout wants it to be, through
   --px-side-w, so `wide` keeps its 340px and the case file keeps its 312px.

   ⚠ align-self:start IS LOAD-BEARING FOR STICKY. A grid item stretches to its row by default, so
   it is already as tall as the track and has nowhere to stick — position:sticky then does nothing
   at all, silently. And when the column is taller than the screen it must scroll INSIDE itself, or
   pinning it makes its lower half unreachable.
   ══════════════════════════════════════════════════════════════════════════════════════════ */
#px-d-grid{--px-side-w:280px}
#px-d-grid.dl-wide{--px-side-w:340px}
#px-d-grid.dl-single-column{--px-side-w:312px}

#px-d-grid.dsp-right{grid-template-columns:minmax(0,1fr) var(--px-side-w)}
#px-d-grid.dsp-right .rq-side{order:0}
#px-d-grid.dsp-left{grid-template-columns:var(--px-side-w) minmax(0,1fr)}
#px-d-grid.dsp-left .rq-side{order:-1}

/* Tabs hides the column entirely and print-friendly deliberately stacks, so neither takes a side. */
/* ═══ LAYOUT 4 — THE CASE TRANSCRIPT ══════════════════════════════════════════════════════════
   This layout drops the sidebar to take the full width, so it must earn that width. Layouts 1/3/5-6
   are chat; layout 2 is mirrored correspondence sheets. This is the third register: a TRANSCRIPT —
   the form minutes, depositions and audit logs take. A fixed meta rail down the left carries who and
   when; a single hairline runs the length of the thread; the words sit to the right of it at full
   measure. No bubbles, no tails, no alternating sides.

   ⚠ SCOPED TO `#px-d-grid.dl-tabs` — one id + one class, which beats every base thread rule (the
   strongest is three classes) and cannot reach the other eight layouts.
   ⚠ ALL COLOUR IS color-mix ON --accent / --ink / --card / --line, so the theme drives it as usual.
   ⚠ NO CSS-GENERATED TEXT anywhere: it cannot be translated. Role is carried by the rail's rule.
   ⚠ `bubble_style`, `bubble_align` and the tail have nothing to act on here, by design. Thread
   order, grouping, day separators, agent HTML and long-message collapse all still apply. */

/* ── THE TAB STRIP ── a real control, not a caption: squared, uppercase, with a live underline. */
#px-d-grid.dl-tabs #px-d-tabs{
  display:flex;gap:0;margin:0 0 2px;
  border-bottom:2px solid color-mix(in srgb,var(--ink) 12%,transparent);
}
#px-d-grid.dl-tabs #px-d-tabs button{
  position:relative;margin:0;padding:11px 18px;
  font-size:11px;font-weight:800;letter-spacing:.13em;text-transform:uppercase;
  color:color-mix(in srgb,var(--ink) 52%,transparent);
  border:0;border-radius:4px 4px 0 0;background:none;
  transition:color .16s var(--ease,ease), background .16s var(--ease,ease);
}
#px-d-grid.dl-tabs #px-d-tabs button::after{
  content:'';position:absolute;left:0;right:0;bottom:-2px;height:2px;
  background:var(--accent);
  transform:scaleX(0);transform-origin:center;
  transition:transform .18s var(--ease,ease);
}
#px-d-grid.dl-tabs #px-d-tabs button:hover{
  color:var(--ink);
  background:color-mix(in srgb,var(--ink) 4%,transparent);
}
#px-d-grid.dl-tabs #px-d-tabs button.on{color:var(--accent)}
#px-d-grid.dl-tabs #px-d-tabs button.on::after{transform:scaleX(1)}

/* ── THE INFORMATION COLUMN, WHEN THE OPERATOR WANTS IT ───────────────────────────────────────
   `dt-side` is the operator's choice to keep the column beside the transcript instead of behind a
   Details tab. The layout's own `grid-template-columns:1fr` and `.rq-side{display:none}` exist only
   to reclaim the width for the tab view, so both are handed back here — and the SIDE the column
   takes is left to the sidebar-side setting, exactly as on every other layout.
   ⚠ Both the layout class and the state class are named, so this outranks the layout's own
   full-width rule (`#px-d-grid.dl-tabs.dsp-left{grid-template-columns:1fr}`, one id + two classes)
   without resorting to !important. */
#px-d-grid.dl-tabs.dt-side .rq-side{display:block}
#px-d-grid.dl-tabs.dt-side.dsp-left{grid-template-columns:var(--px-side-w) minmax(0,1fr)}
#px-d-grid.dl-tabs.dt-side.dsp-right{grid-template-columns:minmax(0,1fr) var(--px-side-w)}
#px-d-grid.dl-tabs.dt-side #px-d-tabs{display:none}
/* With the column present the transcript is narrower, so the meta rail gives ground first. */
#px-d-grid.dl-tabs.dt-side .thread .bubble,
#px-d-grid.dl-tabs.dt-side .thread .brow.mine .bubble{grid-template-columns:112px minmax(0,1fr);column-gap:16px}
#px-d-grid.dl-tabs.dt-side .thread .brow:not(.mine) .bubble{grid-template-columns:112px minmax(0,1fr);column-gap:16px}
@media(max-width:860px){
  #px-d-grid.dl-tabs.dt-side.dsp-left,
  #px-d-grid.dl-tabs.dt-side.dsp-right{grid-template-columns:minmax(0,1fr)}
}

/* ── THE PANELS ── Details reveals the very sidebar this layout hides. */
/* ⚠ ORDER, NOT JUST DISPLAY. `.dl-tabs .rq-side{order:2}` is two classes and LOSES to the sidebar
   side setting's `#px-d-grid.dsp-left .rq-side{order:-1}` (one id + one class), so revealing the
   panel put it BEFORE the letterhead: the ticket information appeared above the page header and the
   tab strip the customer had just clicked was pushed 875px down the page. Naming both layout and
   panel state here is one id + three classes, which wins over the side setting — and it must, since
   in this layout the panel is tab CONTENT and always belongs under its own tab.
   Sticky is dropped for the same reason: a panel that is the whole view has nothing to stick to. */
#px-d-grid.dl-tabs.dt-details .rq-side{
  display:block;order:2!important;
  margin-top:16px;
  position:static!important;top:auto!important;align-self:start!important;
}
#px-d-grid.dl-tabs.dt-details .d-region-thread,
#px-d-grid.dl-tabs.dt-details #px-composer,
#px-d-grid.dl-tabs.dt-details #px-d-bar{display:none}

/* ── THE TRANSCRIPT ── */
#px-d-grid.dl-tabs .thread{
  display:block;gap:0;
  border-top:1px solid var(--line);
  margin-top:14px;
}
#px-d-grid.dl-tabs .thread .brow,
#px-d-grid.dl-tabs .thread .brow.mine{
  display:grid;grid-template-columns:30px minmax(0,1fr);column-gap:12px;
  align-items:start;flex-direction:row;
  max-width:100%;width:100%;margin:0;padding:15px 6px 16px;
  border-bottom:1px solid var(--line);
  transition:background .16s var(--ease,ease);
}
#px-d-grid.dl-tabs .thread .brow:hover{background:color-mix(in srgb,var(--ink) 2.5%,transparent)}
#px-d-grid.dl-tabs .thread .brow.bgroup{border-top:0}

/* the plate is a mark in the margin, not a chat face */
#px-d-grid.dl-tabs .thread .avat{
  grid-column:1;grid-row:1;
  width:28px;height:28px;border-radius:6px;
  font-size:10.5px;font-weight:800;box-shadow:none;
  background:var(--accent-bg,var(--accent));color:var(--card);
}
#px-d-grid.dl-tabs .thread .avat.cust{
  background:color-mix(in srgb,var(--ink) 10%,var(--card));
  color:color-mix(in srgb,var(--ink) 72%,transparent);
  border:1px solid color-mix(in srgb,var(--ink) 14%,transparent);
}

/* ── THE ENTRY ── meta rail left, words right, one hairline between them for the whole thread. */
#px-d-grid.dl-tabs .thread .bubble{
  grid-column:2;grid-row:1;
  max-width:100%;width:100%;margin:0;padding:0;
  background:none!important;border:0!important;border-radius:0!important;box-shadow:none!important;
  display:grid;grid-template-columns:132px minmax(0,1fr);column-gap:20px;row-gap:3px;
}
#px-d-grid.dl-tabs .thread .bubble::after{content:none}   /* no tail in a transcript */
#px-d-grid.dl-tabs .thread .bubble > .who{
  grid-column:1;grid-row:1;margin:0;
  font-size:11px;font-weight:800;letter-spacing:.07em;text-transform:uppercase;
  overflow-wrap:anywhere;
}
#px-d-grid.dl-tabs .thread .bubble > .at{
  grid-column:1;grid-row:2;margin:0;
  font-size:10.5px;font-variant-numeric:tabular-nums;
  color:color-mix(in srgb,var(--ink) 46%,transparent);
}
/* THE SPINE — the rule that makes it a transcript. Accent for the desk, graphite for the client, so
   authorship reads down the page without a second colour system. */
#px-d-grid.dl-tabs .thread .bubble > .body{
  grid-column:2;grid-row:1 / span 2;
  padding-left:20px;
  border-left:2px solid color-mix(in srgb,var(--ink) 14%,transparent);
  font-size:13.5px;line-height:1.62;
}
#px-d-grid.dl-tabs .thread .brow:not(.mine) .bubble > .who{color:var(--accent)}
#px-d-grid.dl-tabs .thread .brow.mine .bubble > .who{color:color-mix(in srgb,var(--ink) 66%,transparent)}

/* ── BOTH VOICES ENTER FROM THE LEFT ──────────────────────────────────────────────────────────
   An earlier pass mirrored the desk to a right-hand rail. With the information column switched on
   the transcript is ~300px narrower, and a right rail there strands the words in a thin middle
   channel — so both voices now share the left rail and the record reads as one continuous column,
   which is what a transcript is.

   ⚠ THE VOICES MUST STILL BE TOLD APART WITHOUT SIDE. Sharing a rail is only acceptable because
   three things still differ: the SPINE colour (accent for the desk, graphite for the client), the
   NAME colour, and the identity plate (accent fill against a bordered neutral). Drop any one of
   those and the transcript reads as a monologue. */
#px-d-grid.dl-tabs .thread .brow:not(.mine){
  grid-template-columns:30px minmax(0,1fr);
}
#px-d-grid.dl-tabs .thread .brow:not(.mine) .avat{grid-column:1;grid-row:1}
#px-d-grid.dl-tabs .thread .brow:not(.mine) .bubble{
  grid-column:2;grid-row:1;
  grid-template-columns:132px minmax(0,1fr);
}
#px-d-grid.dl-tabs .thread .brow:not(.mine) .bubble > .who{grid-column:1;grid-row:1;text-align:left}
#px-d-grid.dl-tabs .thread .brow:not(.mine) .bubble > .at{grid-column:1;grid-row:2;text-align:left}
/* the spine keeps the accent, which is now the main thing separating the two voices */
#px-d-grid.dl-tabs .thread .brow:not(.mine) .bubble > .body{
  grid-column:2;grid-row:1 / span 2;
  padding-left:20px;padding-right:0;
  border-right:0;
  border-left:2px solid var(--accent);
}
#px-d-grid.dl-tabs .thread .brow:not(.mine) .bubble > *:not(.who):not(.at):not(.body){
  grid-column:2;padding-right:0;padding-left:20px;
}
/* everything after the words keeps the same left edge as the words */
#px-d-grid.dl-tabs .thread .bubble > *:not(.who):not(.at):not(.body){
  grid-column:2;padding-left:20px;
}

/* ── THE DAY BAND ── dated across the full width, set in the rail's own column. */
#px-d-grid.dl-tabs .thread .tsep{
  display:block;margin:0;padding:12px 6px 10px;
  background:color-mix(in srgb,var(--ink) 3%,transparent);
  border-bottom:1px solid var(--line);
}
#px-d-grid.dl-tabs .thread .tsep::before,
#px-d-grid.dl-tabs .thread .tsep::after{content:none}
#px-d-grid.dl-tabs .thread .tsep-chip{
  background:none;border:0;padding:0 0 0 42px;border-radius:0;box-shadow:none;
  font-size:10px;font-weight:800;letter-spacing:.18em;text-transform:uppercase;
  color:color-mix(in srgb,var(--ink) 52%,transparent);
}

/* ── THE LETTERHEAD ── squared to match, same as the ledger layout. */
#px-d-grid.dl-tabs #px-d-head{
  padding-bottom:13px;margin-bottom:0;
  border-bottom:2px solid color-mix(in srgb,var(--ink) 14%,transparent);
}
#px-d-grid.dl-tabs #px-d-reply-top{border-radius:5px;box-shadow:none}
#px-d-grid.dl-tabs #px-d-head .d-chip{
  border-radius:4px;padding:4px 10px;font-variant-numeric:tabular-nums;
  background:color-mix(in srgb,var(--ink) 3.5%,transparent);
}
#px-d-grid.dl-tabs #px-d-head #px-live-presence{border-radius:4px}
#px-d-grid.dl-tabs #px-d-actions-top button,
#px-d-grid.dl-tabs #px-d-actions-top a{border-radius:4px}
#px-d-grid.dl-tabs #px-d-convohead{
  margin:0;padding:11px 0 0;letter-spacing:.14em;
  color:color-mix(in srgb,var(--ink) 50%,transparent);
}
#px-d-grid.dl-tabs #px-d-bar{margin:9px 0 4px;padding:0 0 12px;border-bottom:1px solid var(--line)}

/* Narrow: the rail costs more than it gives, so the meta stacks above the words. */
@media(max-width:760px){
  #px-d-grid.dl-tabs .thread .brow,
  #px-d-grid.dl-tabs .thread .brow.mine,
  #px-d-grid.dl-tabs .thread .brow:not(.mine){grid-template-columns:30px minmax(0,1fr)}
  #px-d-grid.dl-tabs .thread .brow:not(.mine) .avat{grid-column:1}
  #px-d-grid.dl-tabs .thread .brow:not(.mine) .bubble{grid-column:2}
  #px-d-grid.dl-tabs .thread .bubble,
  #px-d-grid.dl-tabs .thread .brow.mine .bubble,
  #px-d-grid.dl-tabs .thread .brow:not(.mine) .bubble{grid-template-columns:minmax(0,1fr);row-gap:6px}
  #px-d-grid.dl-tabs .thread .brow:not(.mine) .bubble > .who,
  #px-d-grid.dl-tabs .thread .brow:not(.mine) .bubble > .at{grid-column:1;text-align:left}
  #px-d-grid.dl-tabs .thread .brow:not(.mine) .bubble > .body{
    grid-column:1;grid-row:3;padding-right:0;padding-left:14px;
    border-right:0;border-left:2px solid var(--accent);
  }
  #px-d-grid.dl-tabs .thread .bubble > .who,
  #px-d-grid.dl-tabs .thread .bubble > .at{grid-column:1}
  #px-d-grid.dl-tabs .thread .bubble > .at{grid-row:2}
  #px-d-grid.dl-tabs .thread .bubble > .body{grid-column:1;grid-row:3;padding-left:14px}
  #px-d-grid.dl-tabs .thread .bubble > *:not(.who):not(.at):not(.body){grid-column:1;padding-left:14px}
  #px-d-grid.dl-tabs .thread .tsep-chip{padding-left:0}
}

/* ═══ LAYOUT 5 — THE RECORD CARD ══════════════════════════════════════════════════════════════
   Layout 5's only contribution used to be proportions: `340px 922px` instead of `280px 982px`, a
   WIDER SIDEBAR with layout 1's body untouched. It now takes the card form the OpsIQ inbox uses —
   a full-measure card per message, a round identity disc, the name set beside it in sentence case,
   the timestamp opposite, a hairline, then the words. That is a genuinely different object from
   chat bubbles (1/3), correspondence sheets (2) and the transcript (4).

   ⚠ NO ROLE BADGES. The inbox pairs each card with a CUSTOMER / STAFF pill; those are operator
   furniture and do not belong on a customer's own view — and a `content:` badge could not be
   translated anyway. Authorship is carried by the disc, the surface and the edge.

   ⚠ THE EDGES ARE NOT THE INBOX'S. There a single flat bar marks staff and the customer gets
   nothing. Here BOTH sides carry a gradient edge and they sit on OPPOSITE sides — accent down the
   left for the desk, graphite down the right for the client — so direction reads from the edge
   while the card itself stays full width.

   ⚠ SCOPED TO `#px-d-grid.dl-wide` (one id + one class), which beats every base thread rule and
   reaches no other layout. All colour is color-mix on --accent / --ink / --card / --line. */

#px-d-grid.dl-wide .thread{display:block;gap:0}
#px-d-grid.dl-wide .thread .brow,
#px-d-grid.dl-wide .thread .brow.mine{
  position:relative;display:block;
  width:100%;max-width:100%;margin:0 0 14px;padding:0;
  flex-direction:row;
}

/* THE DISC — round, gradient, and the one place each voice takes its own colour. */
#px-d-grid.dl-wide .thread .avat{
  position:absolute;left:18px;top:16px;
  width:38px;height:38px;border-radius:50%;
  display:flex;align-items:center;justify-content:center;
  font-size:12.5px;font-weight:800;letter-spacing:.01em;
  box-shadow:none;border:0;
  background:linear-gradient(135deg,var(--accent),color-mix(in srgb,var(--accent) 55%,var(--ink)));
  color:var(--card);
  z-index:2;
}
/* ⚠ THE CLIENT NEEDS ITS OWN HUE, NOT A GREY. Derived from --ink the disc and edge were simply a
   paler version of the page's own text colour, so the two voices differed in weight rather than in
   identity. `--warn` is a real design-system token (with --ok and --err), so this is still a token
   and not an invented literal, and it is the one warm value in the system — furthest from the
   accent, which keeps the desk unmistakable. */
#px-d-grid.dl-wide .thread .brow.mine .avat{
  background:linear-gradient(135deg,
    var(--warn),
    color-mix(in srgb,var(--warn) 58%,var(--ink)));
  color:var(--card);
}

/* THE CARD */
#px-d-grid.dl-wide .thread .bubble{
  position:relative;overflow:hidden;
  width:100%;max-width:100%;margin:0;
  padding:16px 20px 17px 68px;
  border-radius:12px;
  background:var(--card);
  border:1px solid var(--line);
  box-shadow:
    0 1px 2px color-mix(in srgb,var(--ink) 5%,transparent),
    0 4px 10px -6px color-mix(in srgb,var(--ink) 12%,transparent);
  display:grid;grid-template-columns:minmax(0,1fr) auto;column-gap:16px;row-gap:0;
  transition:box-shadow .18s var(--ease,ease), border-color .18s var(--ease,ease);
}
#px-d-grid.dl-wide .thread .bubble::after{content:none}   /* no tail on a card */
/* the desk card is tinted, the client's stays on the plain surface */
#px-d-grid.dl-wide .thread .brow:not(.mine) .bubble{
  background:color-mix(in srgb,var(--accent) 4%,var(--card));
  border-color:color-mix(in srgb,var(--accent) 18%,var(--line));
}
/* THE EDGE — gradient, and on opposite sides for the two voices. */
#px-d-grid.dl-wide .thread .bubble::before{
  content:'';position:absolute;top:0;bottom:0;width:3px;
}
#px-d-grid.dl-wide .thread .brow:not(.mine) .bubble::before{
  left:0;
  background:linear-gradient(to bottom,var(--accent),color-mix(in srgb,var(--accent) 42%,transparent));
}
#px-d-grid.dl-wide .thread .brow.mine .bubble::before{
  right:0;
  background:linear-gradient(to bottom,
    var(--warn),
    color-mix(in srgb,var(--warn) 34%,transparent));
}
#px-d-grid.dl-wide .thread .brow:hover .bubble{
  border-color:color-mix(in srgb,var(--accent) 34%,var(--line));
  box-shadow:
    0 2px 4px color-mix(in srgb,var(--ink) 6%,transparent),
    0 10px 22px -10px color-mix(in srgb,var(--accent) 40%,transparent);
}

/* THE HEADER LINE — name beside the disc, time opposite, hairline under both. */
#px-d-grid.dl-wide .thread .bubble > .who{
  grid-column:1;grid-row:1;margin:0;
  font-size:14px;font-weight:800;letter-spacing:-.005em;text-transform:none;
  color:var(--ink);
  align-self:center;
}
#px-d-grid.dl-wide .thread .brow:not(.mine) .bubble > .who{color:var(--ink)}
#px-d-grid.dl-wide .thread .bubble > .at{
  grid-column:2;grid-row:1;margin:0;
  font-size:11.5px;font-variant-numeric:tabular-nums;white-space:nowrap;
  color:color-mix(in srgb,var(--ink) 48%,transparent);
  align-self:center;
}
#px-d-grid.dl-wide .thread .bubble > .body{
  grid-column:1 / -1;grid-row:2;
  margin-top:13px;padding-top:14px;
  border-top:1px solid color-mix(in srgb,var(--ink) 9%,transparent);
  font-size:13.5px;line-height:1.62;
}
#px-d-grid.dl-wide .thread .bubble > *:not(.who):not(.at):not(.body){grid-column:1 / -1}

/* ── RATING AND REACTION, ON THE EDGE ────────────────────────────────────────────────────────
   Both sat full-width under the message with their prompts spelled out, so every card ended in a
   line of instructions. They now share one row hard against the card's right edge, reduced to the
   marks themselves: five stars and the thumb.

   ⚠ THE WORDING IS HIDDEN FROM SIGHT, NOT DELETED. `display:none` would also remove it from the
   accessibility tree — and "Like" IS that button's accessible name (the markup is
   `👍 <span class="rx-t">Like</span>`), so a screen reader would announce a bare emoji. Clipping
   keeps the name and the prompt available while showing neither. */
/* ⚠ THE LIKE MOVES WITH THE STARS BUT KEEPS ITS OWN STYLING. Stripping its chrome made it read as
   decoration rather than as something to press, so only its POSITION changes: it sits on the same
   row, hard against the same edge, still a pill with its border, fill and label. */
/* ⚠ EACH ON ITS OWN ROW, BOTH SPANNING THE FULL WIDTH. Sharing row 3 put the stars in column 1 and
   the Like in column 2 — but column 2 is `auto`, sized to the timestamp, so the pill was laid over
   the stars and the two collided. Spanning both columns and stacking them keeps each flush to the
   same right edge with nothing to overlap. */
#px-d-grid.dl-wide .thread .bubble > .rr,
#px-d-grid.dl-wide .thread .bubble > .rx{
  grid-column:1 / -1;
  justify-self:end;align-self:center;
}
#px-d-grid.dl-wide .thread .bubble > .rr{
  grid-row:3;margin-top:12px;
  gap:0;margin-bottom:0;padding:0;border:0;background:none;
}
#px-d-grid.dl-wide .thread .bubble > .rx{grid-row:4;margin:8px 0 0}
#px-d-grid.dl-wide .thread .rr .rr-label{
  position:absolute;width:1px;height:1px;
  padding:0;margin:-1px;overflow:hidden;
  clip-path:inset(50%);white-space:nowrap;border:0;
}
#px-d-grid.dl-wide .thread .rr .rr-star{
  padding:0 2px;font-size:22px;line-height:1;
  background:none;border:0;
}

/* THE DAY BAND */
#px-d-grid.dl-wide .thread .tsep{
  display:block;margin:18px 0 12px;padding:0 0 8px;
  border-bottom:1px solid var(--line);
}
#px-d-grid.dl-wide .thread .tsep::before,
#px-d-grid.dl-wide .thread .tsep::after{content:none}
#px-d-grid.dl-wide .thread .tsep-chip{
  background:none;border:0;padding:0;border-radius:0;box-shadow:none;
  font-size:10px;font-weight:800;letter-spacing:.18em;text-transform:uppercase;
  color:color-mix(in srgb,var(--ink) 50%,transparent);
}

@media(max-width:640px){
  #px-d-grid.dl-wide .thread .avat{width:30px;height:30px;left:14px;top:14px}
  #px-d-grid.dl-wide .thread .bubble{padding:14px 15px 15px 54px}
  #px-d-grid.dl-wide .thread .bubble > .who{font-size:13px}
}

/* ═══ LAYOUT 6 — THE FILE CARD ════════════════════════════════════════════════════════════════
   Same FAMILY as layout 5 — the OpsIQ inbox card, a disc with the name and time beside it, then
   the words — but treated as the opposite object. Layout 5 is soft: rounded 12px, drop shadow,
   round gradient disc, sentence-case name, header floating on the card surface, a gradient hairline
   down one edge. This is hard: a SQUARE 3px corner, no shadow at all, a filled HEADER BAND that the
   disc and name sit inside, a rounded-square disc, the name in letterspaced caps, monospace time,
   and a 3px rule across the TOP of the card rather than down its side.

   Read down a thread the difference is immediate: layout 5 is a stack of soft tiles, this is a stack
   of filed documents.

   ⚠ SCOPED TO `#px-d-grid.dl-print-friendly` — one id + one class, beats every base thread rule,
   reaches no other layout. All colour is color-mix on --accent / --warn / --ink / --card / --line,
   the same two voice hues layout 5 uses so the set stays coherent.
   ⚠ NO CSS-GENERATED TEXT: it cannot be translated. */

#px-d-grid.dl-print-friendly .thread{display:block;gap:0}
#px-d-grid.dl-print-friendly .thread .brow,
#px-d-grid.dl-print-friendly .thread .brow.mine{
  position:relative;display:block;
  width:100%;max-width:100%;margin:0 0 12px;padding:0;
  flex-direction:row;
}

/* THE CARD — squared, flat, and topped by a rule in the voice's colour. */
#px-d-grid.dl-print-friendly .thread .bubble{
  position:relative;overflow:hidden;
  width:100%;max-width:100%;margin:0;padding:0;
  border-radius:3px;
  background:var(--card);
  border:1px solid var(--line);
  border-top:3px solid var(--accent);
  box-shadow:none;
  display:block;
}
#px-d-print-friendly .thread .bubble::after,
#px-d-grid.dl-print-friendly .thread .bubble::after{content:none}   /* no tail on a document */
#px-d-grid.dl-print-friendly .thread .brow.mine .bubble{border-top-color:var(--warn)}

/* THE HEADER BAND — filled, not floating. This is the single biggest departure from layout 5. */
#px-d-grid.dl-print-friendly .thread .bubble > .who{
  display:block;margin:0;
  padding:11px 14px 11px 52px;
  background:color-mix(in srgb,var(--accent) 7%,var(--card));
  border-bottom:1px solid color-mix(in srgb,var(--accent) 16%,var(--line));
  font-size:10.5px;font-weight:800;letter-spacing:.14em;text-transform:uppercase;
  color:color-mix(in srgb,var(--ink) 84%,transparent);
  min-height:44px;line-height:22px;
}
#px-d-grid.dl-print-friendly .thread .brow.mine .bubble > .who{
  background:color-mix(in srgb,var(--warn) 9%,var(--card));
  border-bottom-color:color-mix(in srgb,var(--warn) 22%,var(--line));
}
/* THE DISC — a rounded SQUARE sitting inside the band, not a circle floating over the card. */
#px-d-grid.dl-print-friendly .thread .avat{
  position:absolute;left:14px;top:12px;
  width:26px;height:26px;border-radius:7px;
  display:flex;align-items:center;justify-content:center;
  font-size:10px;font-weight:800;letter-spacing:.02em;
  box-shadow:none;border:0;
  background:var(--accent);color:var(--card);
  z-index:2;
}
#px-d-grid.dl-print-friendly .thread .brow.mine .avat{background:var(--warn);color:var(--card)}

/* THE TIME — monospace, in the band, hard right. */
#px-d-grid.dl-print-friendly .thread .bubble > .at{
  position:absolute;top:0;right:14px;
  margin:0;height:44px;display:flex;align-items:center;
  font-family:ui-monospace,Menlo,Consolas,monospace;
  font-size:10.5px;font-variant-numeric:tabular-nums;letter-spacing:-.01em;
  color:color-mix(in srgb,var(--ink) 52%,transparent);
  z-index:2;
}

/* THE WORDS */
#px-d-grid.dl-print-friendly .thread .bubble > .body{
  margin:0;padding:15px 16px 16px;
  font-size:13.5px;line-height:1.62;
  border:0;
}
#px-d-grid.dl-print-friendly .thread .bubble > *:not(.who):not(.at):not(.body){
  margin:0;padding:0 16px 14px;
}
/* the marks sit right, as on layout 5, but with no row of their own to hang under */
#px-d-grid.dl-print-friendly .thread .bubble > .rr{
  display:flex;justify-content:flex-end;
  gap:0;border:0;background:none;
}
#px-d-grid.dl-print-friendly .thread .rr .rr-label{
  position:absolute;width:1px;height:1px;padding:0;margin:-1px;
  overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0;
}
#px-d-grid.dl-print-friendly .thread .rr .rr-star{padding:0 2px;font-size:19px;line-height:1;background:none;border:0}
#px-d-grid.dl-print-friendly .thread .bubble > .rx{display:flex;justify-content:flex-end}

/* THE DAY BAND — a filed divider, flush and ruled top and bottom. */
#px-d-grid.dl-print-friendly .thread .tsep{
  display:block;margin:16px 0 12px;padding:7px 0;
  border-top:1px solid var(--line);
  border-bottom:1px solid var(--line);
  background:color-mix(in srgb,var(--ink) 3%,transparent);
}
#px-d-grid.dl-print-friendly .thread .tsep::before,
#px-d-grid.dl-print-friendly .thread .tsep::after{content:none}
#px-d-grid.dl-print-friendly .thread .tsep-chip{
  background:none;border:0;padding:0 14px;border-radius:0;box-shadow:none;
  font-size:9.5px;font-weight:800;letter-spacing:.2em;text-transform:uppercase;
  color:color-mix(in srgb,var(--ink) 54%,transparent);
}

/* ── PRINT ── the layout that claims the name should actually earn it. */
@media print{
  #px-d-grid.dl-print-friendly .thread .bubble{border:1px solid var(--line);border-top-width:2px}
  #px-d-grid.dl-print-friendly .thread .bubble > .who{background:none;padding-left:14px}
  #px-d-grid.dl-print-friendly .thread .avat{display:none}
  #px-d-grid.dl-print-friendly .thread .brow{break-inside:avoid;page-break-inside:avoid}
  #px-d-grid.dl-print-friendly .thread .rr,
  #px-d-grid.dl-print-friendly .thread .rx{display:none}
}

/* ═══ LAYOUT 7 — THE GLASS CARD ═══════════════════════════════════════════════════════════════
   The third member of the inbox-card family, and the quiet one. Layout 5 is soft and shadowed,
   layout 6 is squared and filed; this is FROSTED — a translucent pane with a wide radius, a
   specular top edge, and almost no ornament. Restraint is the design: no filled band, no heavy
   rules, no uppercase. Structure comes from spacing, light and material.

   ⚠ THE OLD DEFINITION IS GONE, AND IT NEVER WORKED ANYWAY. It was one line: a
   `grid-template-columns: minmax(0,1fr) 330px` plus a bigger radius and a hardcoded slate shadow
   literal. The grid half was overruled on every render by the sidebar-side setting
   (`#px-d-grid.dsp-left`, one id + one class, against two classes), so its own column rule never
   applied. Which side the column takes is the operator's setting on every other layout, and it is
   here too.

   ⚠ SCOPED TO `#px-d-grid.dl-case-workspace`; all colour is color-mix on --accent / --warn / --ink /
   --card / --line, the same two voice hues as layouts 5 and 6 so the family reads as one set. */

#px-d-grid.dl-case-workspace .thread{display:block;gap:0}
#px-d-grid.dl-case-workspace .thread .brow,
#px-d-grid.dl-case-workspace .thread .brow.mine{
  position:relative;display:block;
  width:100%;max-width:100%;margin:0 0 12px;padding:0;
  flex-direction:row;
}

/* THE PANE */
#px-d-grid.dl-case-workspace .thread .bubble{
  position:relative;overflow:hidden;
  width:100%;max-width:100%;margin:0;
  padding:15px 20px 17px 62px;
  border-radius:20px;
  background:color-mix(in srgb,var(--card) 58%,transparent)!important;
  border:1px solid color-mix(in srgb,var(--card) 62%,var(--line))!important;
  box-shadow:
    inset 0 1px 0 color-mix(in srgb,var(--card) 92%,transparent),
    0 1px 2px color-mix(in srgb,var(--ink) 4%,transparent),
    0 12px 30px -18px color-mix(in srgb,var(--ink) 26%,transparent)!important;
  display:grid;grid-template-columns:minmax(0,1fr) auto;column-gap:16px;
  transition:transform .22s var(--ease,cubic-bezier(.2,.7,.3,1)),
             box-shadow .22s var(--ease,ease),
             border-color .22s var(--ease,ease),
             background .22s var(--ease,ease);
}
@supports (backdrop-filter:blur(1px)){
  #px-d-grid.dl-case-workspace .thread .bubble{backdrop-filter:blur(22px) saturate(1.7)}
}
#px-d-grid.dl-case-workspace .thread .bubble::after{content:none}

/* THE EDGE — a rounded indicator inset from the rim, not a bar welded to it. It GROWS on hover. */
#px-d-grid.dl-case-workspace .thread .bubble::before{
  content:'';position:absolute;left:14px;top:22px;
  width:3px;height:20px;border-radius:3px;
  background:var(--accent);
  opacity:.85;
  transition:height .22s var(--ease,cubic-bezier(.2,.7,.3,1)),
             opacity .22s var(--ease,ease), top .22s var(--ease,ease);
}
#px-d-grid.dl-case-workspace .thread .brow.mine .bubble::before{background:var(--warn)}

/* HOVER — the pane lifts and clarifies, the edge extends. */
#px-d-grid.dl-case-workspace .thread .brow:hover .bubble{
  transform:translateY(-2px);
  background:color-mix(in srgb,var(--card) 76%,transparent)!important;
  border-color:color-mix(in srgb,var(--card) 40%,var(--accent))!important;
  box-shadow:
    inset 0 1px 0 color-mix(in srgb,var(--card) 96%,transparent),
    0 2px 6px color-mix(in srgb,var(--ink) 6%,transparent),
    0 22px 48px -22px color-mix(in srgb,var(--accent) 46%,transparent)!important;
}
#px-d-grid.dl-case-workspace .thread .brow.mine:hover .bubble{
  border-color:color-mix(in srgb,var(--card) 40%,var(--warn))!important;
  box-shadow:
    inset 0 1px 0 color-mix(in srgb,var(--card) 96%,transparent),
    0 2px 6px color-mix(in srgb,var(--ink) 6%,transparent),
    0 22px 48px -22px color-mix(in srgb,var(--warn) 46%,transparent)!important;
}
#px-d-grid.dl-case-workspace .thread .brow:hover .bubble::before{
  top:18px;height:calc(100% - 36px);opacity:1;
}

/* THE DISC — frosted, ringed, no gradient. */
#px-d-grid.dl-case-workspace .thread .avat{
  position:absolute;left:24px;top:19px;
  width:28px;height:28px;border-radius:50%;
  display:flex;align-items:center;justify-content:center;
  font-size:10.5px;font-weight:700;letter-spacing:0;
  background:color-mix(in srgb,var(--accent) 16%,var(--card));
  color:color-mix(in srgb,var(--accent) 88%,var(--ink));
  border:1px solid color-mix(in srgb,var(--accent) 26%,transparent);
  box-shadow:none;z-index:2;
  transition:transform .22s var(--ease,cubic-bezier(.2,.7,.3,1));
}
#px-d-grid.dl-case-workspace .thread .brow.mine .avat{
  background:color-mix(in srgb,var(--warn) 18%,var(--card));
  color:color-mix(in srgb,var(--warn) 78%,var(--ink));
  border-color:color-mix(in srgb,var(--warn) 30%,transparent);
}
#px-d-grid.dl-case-workspace .thread .brow:hover .avat{transform:scale(1.06)}

/* TYPE — medium weight, tight tracking, sentence case. No shouting. */
#px-d-grid.dl-case-workspace .thread .bubble > .who{
  grid-column:1;grid-row:1;margin:0;
  font-size:13.5px;font-weight:600;letter-spacing:-.012em;text-transform:none;
  color:var(--ink);align-self:center;
}
#px-d-grid.dl-case-workspace .thread .bubble > .at{
  grid-column:2;grid-row:1;margin:0;
  font-size:11.5px;font-weight:500;font-variant-numeric:tabular-nums;white-space:nowrap;
  color:color-mix(in srgb,var(--ink) 42%,transparent);align-self:center;
}
/* separated by air, not by a rule */
#px-d-grid.dl-case-workspace .thread .bubble > .body{
  grid-column:1 / -1;grid-row:2;
  margin-top:9px;padding-top:0;border-top:0;
  font-size:13.5px;line-height:1.65;
  color:color-mix(in srgb,var(--ink) 92%,transparent);
}
#px-d-grid.dl-case-workspace .thread .bubble > *:not(.who):not(.at):not(.body){grid-column:1 / -1}
#px-d-grid.dl-case-workspace .thread .bubble > .rr{
  display:flex;justify-content:flex-end;margin-top:10px;gap:0;border:0;background:none;
}
#px-d-grid.dl-case-workspace .thread .rr .rr-label{
  position:absolute;width:1px;height:1px;padding:0;margin:-1px;
  overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0;
}
#px-d-grid.dl-case-workspace .thread .rr .rr-star{padding:0 2px;font-size:19px;line-height:1;background:none;border:0}
#px-d-grid.dl-case-workspace .thread .bubble > .rx{display:flex;justify-content:flex-end;margin-top:8px}

/* THE DAY BAND — a whisper. */
#px-d-grid.dl-case-workspace .thread .tsep{
  display:block;margin:20px 0 12px;padding:0;border:0;background:none;text-align:center;
}
#px-d-grid.dl-case-workspace .thread .tsep::before,
#px-d-grid.dl-case-workspace .thread .tsep::after{content:none}
#px-d-grid.dl-case-workspace .thread .tsep-chip{
  display:inline-block;
  background:color-mix(in srgb,var(--card) 62%,transparent);
  border:1px solid color-mix(in srgb,var(--card) 60%,var(--line));
  border-radius:999px;padding:5px 14px;box-shadow:none;
  font-size:10.5px;font-weight:600;letter-spacing:.04em;text-transform:none;
  color:color-mix(in srgb,var(--ink) 52%,transparent);
}

@media(prefers-reduced-motion:reduce){
  #px-d-grid.dl-case-workspace .thread .brow:hover .bubble{transform:none}
  #px-d-grid.dl-case-workspace .thread .brow:hover .avat{transform:none}
}

/* ═══ LAYOUT 8 — THE TWO RAILS ════════════════════════════════════════════════════════════════
   The name finally means something. It used to be one line — `grid-template-columns:300px 1fr`
   plus `.rq-side{order:-1}` — which is sidebar-LEFT with a single rail, so a customer choosing
   "dual sidebar" got one sidebar moved left. There was never a second column.

   ⚠ THE SPLIT NEEDS NO MARKUP CHANGE, because `.rq-side` holds EXACTLY TWO children: the
   ticket-information card, and the `.swrap` wrapper carrying the other three (other
   requests, related help, need more help). `display:contents` dissolves the wrapper's own box so
   those two become grid items of the detail grid itself, and each can take its own column.
   Left rail = the FACTS about this request. Right rail = everything AROUND it.

   ⚠ BOTH LAYOUT AND SIDE CLASSES ARE NAMED on the column rule. `#px-d-grid.dl-dual-sidebar` alone
   is one id + one class — the same weight as the sidebar-side setting's `#px-d-grid.dsp-left`, so
   it would tie and lose on source order, exactly as the old stub did. Naming both wins outright.
   Side has no meaning here anyway: with a rail on each flank there is no side left to choose.

   ⚠ THIS LAYOUT'S IDENTITY IS ITS STRUCTURE, NOT ITS MESSAGES. Layouts 5, 6 and 7 each restyle the
   thread; this one deliberately leaves the conversation alone and earns its place on the columns.

   Colour is color-mix on --ink / --card / --line / --accent throughout. */

/* ⚠ grid-template-rows IS REQUIRED, or the rails hang 800px apart. The thread spans BOTH rows, so
   with implicit rows the grid shares its height between them — row 1 grew to half the conversation
   and the second card in each rail was pushed far down the page (measured: card tops at 320 and
   1148). `auto 1fr` sizes row 1 to its content and gives every remaining pixel to row 2, so the
   second card sits directly under the first. */
#px-d-grid.dl-dual-sidebar.dsp-left,
#px-d-grid.dl-dual-sidebar.dsp-right{
  grid-template-columns:278px minmax(0,1fr) 278px;
  grid-template-rows:auto 1fr;
  column-gap:20px;row-gap:14px;
  align-items:start;
}
/* ⚠ BOTH WRAPPERS DISSOLVE, SO EVERY CARD IS PLACEABLE. `.rq-side` alone gave two rails but the
   three cards inside `.swrap` were locked together in one box — "Need more help?" could not
   leave the right rail. Dissolving that wrapper too makes all four cards grid items in their own
   right, so each can be sent to either rail.
   ⚠ THE LAST CARD IS TARGETED BY :last-child, NOT nth-child(3). A ticket with no other requests
   renders fewer cards, and a fixed index would then move the wrong one. */
#px-d-grid.dl-dual-sidebar .rq-side,
#px-d-grid.dl-dual-sidebar .rq-side > .swrap{display:contents}
/* LEFT RAIL — the facts, and the help card beneath them. */
#px-d-grid.dl-dual-sidebar .rq-side > .side-card{grid-column:1;grid-row:1;order:0}
#px-d-grid.dl-dual-sidebar .rq-side > .swrap > .side-card:last-child{grid-column:1;grid-row:2}
/* RIGHT RAIL — everything else. */
#px-d-grid.dl-dual-sidebar .rq-side > .swrap > .side-card{grid-column:3;order:0}
/* THE THREAD spans both rows so the rails can stack beside it. */
#px-d-grid.dl-dual-sidebar .rq-main{grid-column:2;grid-row:1 / span 2;min-width:0}
/* ⚠ align-items:start ON THE ROWS, or a short card stretches to its row's height and the two rails
   no longer start level. This is what left the right rail hanging below the left. */
/* ⚠ STRETCH BELONGS TO ROW 1 ONLY. Row 1 is `auto`, so stretching its two cards makes them match
   each other exactly (they were 360 against 348). Row 2 is `1fr` — it takes ALL the remaining
   height — so stretching those cards blew them up to 1122px each: two enormous boxes of empty space
   where "Related help" and "Need more help?" should be. Row 2 stays at its content height. */
#px-d-grid.dl-dual-sidebar .rq-side > .side-card,
#px-d-grid.dl-dual-sidebar .rq-side > .swrap > .side-card:first-child{align-self:stretch}
#px-d-grid.dl-dual-sidebar .rq-side > .swrap > .side-card:not(:first-child){align-self:start}
/* ⚠ THE SIDE SETTING MUST STILL MEAN SOMETHING HERE. With a rail on each flank there is no side
   left to move a sidebar to — so the setting decides WHICH RAIL HOLDS THE FACTS instead. Left puts
   the ticket information on the left and the surrounding cards on the right; right swaps them.
   Without this the control was inert on this layout, which is the same dead-setting problem the old
   stub had. */
#px-d-grid.dl-dual-sidebar.dsp-right .rq-side > .side-card{grid-column:3}
#px-d-grid.dl-dual-sidebar.dsp-right .rq-side > .swrap{grid-column:1}
#px-d-grid.dl-dual-sidebar.dsp-right{grid-template-columns:278px minmax(0,1fr) 278px}

/* Each rail follows the reader on its own, rather than one long column doing it for both. */
/* ⚠ STICK, BUT DO NOT STACK. Making every card sticky at the SAME offset is precisely what stacks
   them: each one pins to the same line and the next slides underneath it, ending as a pile. Only
   the card at the TOP of each rail holds; the one beneath it scrolls past normally, so a rail never
   collects more than one pinned card.
   ⚠ THE REST MUST BE SET BACK TO static EXPLICITLY. The generic sticky-mode rules already pin
   `.rq-side > .side-card`, so leaving them alone is not the same as switching them off. */
/* ⚠ BOTH STICKY-MODE CLASSES MUST BE NAMED, AGAIN. `#px-d-grid.dss-sticky.dss-fits .rq-side
   .side-card{position:static}` is one id + four classes — the same weight as this rule was — and it
   sits later in the file, so it won and the ticket card never pinned. Measured: computed `static`
   with that rule listed as the last match. Naming the mode class here puts this at one id + FIVE
   and settles it outright. */
/* ⚠ EVERY CARD PINS, AND NONE MAY CLIMB. Both cards in a rail stick — but two sticky cards sharing
   one `top` pin to the SAME line, so the lower one rides up over the upper one. The second card in
   each rail therefore pins one CARD-HEIGHT lower, and that height is measured in
   pxSideStickyMode() and published as --px-rail-l / --px-rail-r (the ticket card's height varies
   with how many fields the operator shows, so it cannot be a constant here).
   The fallback in each var() is a sane offset for the moment before the first measurement lands. */
#px-d-grid.dl-dual-sidebar.dss-sticky.dss-fits .rq-side > .side-card,
#px-d-grid.dl-dual-sidebar.dss-sticky.dss-tall .rq-side > .side-card,
#px-d-grid.dl-dual-sidebar.dss-sticky.dss-fits .rq-side > .swrap > .side-card,
#px-d-grid.dl-dual-sidebar.dss-sticky.dss-tall .rq-side > .swrap > .side-card{
  position:sticky;
}
/* row 1 of each rail — pinned at the nav */
#px-d-grid.dl-dual-sidebar.dss-sticky.dss-fits .rq-side > .side-card,
#px-d-grid.dl-dual-sidebar.dss-sticky.dss-tall .rq-side > .side-card,
#px-d-grid.dl-dual-sidebar.dss-sticky.dss-fits .rq-side > .swrap > .side-card:first-child,
#px-d-grid.dl-dual-sidebar.dss-sticky.dss-tall .rq-side > .swrap > .side-card:first-child{
  top:calc(var(--px-navh,0px) + 14px);
}
/* row 2 of each rail — pinned exactly below its own rail's first card, so they sit one under the
   other rather than one on top of the other.

   ⚠ NOT :nth-child(2). That counts EVERY child, so it only lands on the right card while the
   wrapper contains nothing but cards and exactly three of them — a ticket with no other requests
   renders fewer, and the offset then attaches to the wrong card or to none, which is what left the
   right rail climbing. `:not(:first-child)` is true of every card after the leader regardless of how
   many there are. The left rail's card is then re-pointed at its own offset by the rule after it. */
#px-d-grid.dl-dual-sidebar.dss-sticky.dss-fits .rq-side > .swrap > .side-card:not(:first-child),
#px-d-grid.dl-dual-sidebar.dss-sticky.dss-tall .rq-side > .swrap > .side-card:not(:first-child){
  top:var(--px-rail-r,470px);
}
#px-d-grid.dl-dual-sidebar.dss-sticky.dss-fits .rq-side > .swrap > .side-card:last-child,
#px-d-grid.dl-dual-sidebar.dss-sticky.dss-tall .rq-side > .swrap > .side-card:last-child{
  top:var(--px-rail-l,470px);
}

/* ⚠ THE LAYER RULES WERE LOST IN AN EARLIER REWRITE OF THIS BLOCK, and without them a card that does
   reach another paints straight over it — which is why "Related help" cut across "Your other
   tickets" instead of stopping beneath it. The leader of each rail stays in front. */
#px-d-grid.dl-dual-sidebar .rq-side > .side-card,
#px-d-grid.dl-dual-sidebar .rq-side > .swrap > .side-card{position:relative;z-index:1}
#px-d-grid.dl-dual-sidebar.dss-sticky .rq-side > .side-card,
#px-d-grid.dl-dual-sidebar.dss-sticky .rq-side > .swrap > .side-card:first-child{z-index:2}

/* THE LEFT RAIL — the record. Denser, quieter, squared off against the thread. */
#px-d-grid.dl-dual-sidebar .rq-side > .side-card{
  border-radius:14px;
}
/* THE RIGHT RAIL — what surrounds the request. Lighter, so the eye reads left first. */
#px-d-grid.dl-dual-sidebar .rq-side > .swrap > .side-card{
  border-radius:14px;
  background:color-mix(in srgb,var(--card) 74%,transparent);
}
#px-d-grid.dl-dual-sidebar .rq-side > .swrap .smc-h{
  font-size:10.5px;letter-spacing:.13em;
  color:color-mix(in srgb,var(--ink) 54%,transparent);
}

/* ── THE MESSAGE CARDS ────────────────────────────────────────────────────────────────────────
   ⚠ FULL MEASURE, WHATEVER THE MESSAGE. A chat bubble sizes itself to its text, so "Please escalate
   this" rendered as a stub beside a paragraph-length reply and the column looked ragged. Here every
   message takes the full width of the thread, so a one-line note and a long answer are the same
   object at different heights — which is what the two-rail layout's squarer register wants. */
/* ⚠ A GUTTER ON BOTH SIDES OF EVERY ROW. The desk's disc sits left and the client's sits right, so
   each row reserved space on only ONE flank — the two cards were different rectangles and their text
   started at different x (measured 156 against 68). Full-width cards made that impossible to miss.
   Both gutters are now reserved on every row and the card always occupies the middle column, so the
   name, the words and the timestamp line up down the whole thread; only the gutter that is FILLED
   changes side. */
/* ⚠ THE RIGHT GUTTER IS GONE NOW THAT BOTH DISCS SIT LEFT. It was reserved so the two cards stayed
   the same rectangle while the discs were on opposite flanks; with both in one column it was 49px
   of dead space on every row, and the cards were narrower for nothing. Two columns, so the card
   takes the width back — and they are still identical rectangles because neither has a right gutter
   now. */
#px-d-grid.dl-dual-sidebar .thread .brow,
#px-d-grid.dl-dual-sidebar .thread .brow.mine{
  display:grid;grid-template-columns:38px minmax(0,1fr);column-gap:11px;
  align-items:start;flex-direction:row;
}
#px-d-grid.dl-dual-sidebar .thread .brow .bubble{grid-column:2;grid-row:1}
/* ⚠ THE CLIENT READS RIGHT, THE DESK READS LEFT. Both cards fill the same full-width rectangle, so
   without this the only thing separating the two voices was a border colour. The client's name,
   words and timestamp now set to the right and its 3px edge moves to the right with them, mirroring
   the desk exactly. The 2px text offset that started this (names at 468 against 466, caused by the
   desk's 3px rule against the client's 1px) disappears with it, since each card now carries a 3px
   edge on its own side. */
#px-d-grid.dl-dual-sidebar .thread .brow.mine .bubble{
  border-left:3px solid color-mix(in srgb,var(--warn) 55%,var(--line));
  border-right:1px solid color-mix(in srgb,var(--warn) 30%,var(--line));
  text-align:left;
}
#px-d-grid.dl-dual-sidebar .thread .brow.mine .bubble .who,
#px-d-grid.dl-dual-sidebar .thread .brow.mine .bubble .body,
#px-d-grid.dl-dual-sidebar .thread .brow.mine .bubble .at{text-align:left}
/* ⚠ THE TEXT DOES NOT MIRROR — ONLY THE FURNITURE DOES. Setting the desk's words right-aligned was
   a real mirror and it read badly: a ragged left margin means the eye loses the start of every line,
   which is why a paragraph set right feels wrong however neat the card looks. Both voices read from
   the left; the SIDE is carried by the disc's gutter, the solid rule and the corner notch, which
   cost nothing in legibility. */
#px-d-grid.dl-dual-sidebar .thread .brow:not(.mine) .bubble{
  border-left:1px solid color-mix(in srgb,var(--accent) 24%,var(--line));
  border-right:3px solid var(--accent);
  text-align:left;
}
#px-d-grid.dl-dual-sidebar .thread .brow:not(.mine) .bubble .who,
#px-d-grid.dl-dual-sidebar .thread .brow:not(.mine) .bubble .body,
#px-d-grid.dl-dual-sidebar .thread .brow:not(.mine) .bubble .at{text-align:left}
/* the marks sit on the card's own outer edge, which still reads as direction without moving prose */
#px-d-grid.dl-dual-sidebar .thread .brow.mine .bubble .rr,
#px-d-grid.dl-dual-sidebar .thread .brow.mine .bubble .rx{justify-content:flex-start}
#px-d-grid.dl-dual-sidebar .thread .brow:not(.mine) .bubble .rr,
#px-d-grid.dl-dual-sidebar .thread .brow:not(.mine) .bubble .rx{justify-content:flex-end}
/* ⚠ A TRUE MIRROR, NOT JUST A FLIPPED ALIGNMENT. Measured against the desk card, three things were
   still not reflected: the desk names itself in the ACCENT while the client's name stayed a muted
   grey; the tracking differed (0.5px against 0.4px); and the desk's corner notch sits bottom-LEFT
   (`14px 14px 14px 6px`) while the client had four equal corners, so the card had no answering
   notch on its own side. Each is now mirrored, so the two cards are the same object reflected. */
#px-d-grid.dl-dual-sidebar .thread .brow.mine .bubble > .who{
  color:color-mix(in srgb,var(--warn) 72%,var(--ink));
  letter-spacing:.5px;
}
#px-d-grid.dl-dual-sidebar .thread .brow.mine .bubble{
  border-radius:14px 14px 14px 6px;
}
#px-d-grid.dl-dual-sidebar .thread .brow:not(.mine) .bubble{
  border-radius:14px 14px 6px 14px;
}
/* ⚠ BOTH DISCS ON THE LEFT. Splitting them across the two gutters was a real mirror, but it made
   the eye jump side to side down a list of full-width cards and gave the desk's card a ragged left
   margin to match. One column of discs reads as a single record; WHO is still unmistakable from the
   disc's own colour, the solid rule and the corner notch.
   The right gutter is kept reserved so both cards remain the identical rectangle. */
#px-d-grid.dl-dual-sidebar .thread .brow.mine .avat,
#px-d-grid.dl-dual-sidebar .thread .brow:not(.mine) .avat{grid-column:1;grid-row:1}
#px-d-grid.dl-dual-sidebar .thread .bubble{
  width:100%;max-width:100%;flex:1 1 auto;
  transition:border-color .18s var(--ease,ease), box-shadow .18s var(--ease,ease),
             background .18s var(--ease,ease);
}
/* ── HOVER ── the card under the cursor lifts and takes its own voice's colour. */
#px-d-grid.dl-dual-sidebar .thread .brow:hover .bubble{
  background:var(--card)!important;
  border-color:color-mix(in srgb,var(--accent) 38%,var(--line))!important;
  box-shadow:
    0 1px 2px color-mix(in srgb,var(--ink) 6%,transparent),
    0 10px 24px -12px color-mix(in srgb,var(--accent) 45%,transparent)!important;
}
#px-d-grid.dl-dual-sidebar .thread .brow.mine:hover .bubble{
  border-color:color-mix(in srgb,var(--warn) 42%,var(--line))!important;
  box-shadow:
    0 1px 2px color-mix(in srgb,var(--ink) 6%,transparent),
    0 10px 24px -12px color-mix(in srgb,var(--warn) 45%,transparent)!important;
}
/* the identity disc answers the hover so the row reads as one object */
#px-d-grid.dl-dual-sidebar .thread .avat{transition:box-shadow .18s var(--ease,ease)}
#px-d-grid.dl-dual-sidebar .thread .brow:hover .avat{
  box-shadow:0 0 0 3px color-mix(in srgb,var(--accent) 20%,transparent);
}
#px-d-grid.dl-dual-sidebar .thread .brow.mine:hover .avat{
  box-shadow:0 0 0 3px color-mix(in srgb,var(--warn) 22%,transparent);
}

/* Below three comfortable columns the rails stack under the conversation, facts first. */
@media(max-width:860px){
  #px-d-grid.dl-dual-sidebar.dsp-left,
  #px-d-grid.dl-dual-sidebar.dsp-right{grid-template-columns:minmax(0,1fr)}
  #px-d-grid.dl-dual-sidebar .rq-main{grid-column:1;grid-row:1}
  #px-d-grid.dl-dual-sidebar .rq-main{grid-column:1;grid-row:1}
  #px-d-grid.dl-dual-sidebar .rq-side > .side-card{grid-column:1;grid-row:auto}
  #px-d-grid.dl-dual-sidebar .rq-side > .swrap > .side-card,
  #px-d-grid.dl-dual-sidebar .rq-side > .swrap > .side-card:last-child{grid-column:1;grid-row:auto}
  #px-d-grid.dl-dual-sidebar.dss-sticky .rq-side > .side-card,
  #px-d-grid.dl-dual-sidebar.dss-sticky .rq-side > .swrap > .side-card{position:static}
}

/* ── LAYOUT 8 × THE PANEL DESIGNS ─────────────────────────────────────────────────────────────
   ⚠ THREE OF THE SIX SIDEBAR DESIGNS DRAW THEIR SURFACE ON `.rq-side` ITSELF — rail, glass and
   slab all treat the column as one continuous panel. This layout dissolves that box with
   `display:contents` to get its two rails, so on those three the panel simply never rendered:
   measured `sideBoxRendered:false`, and glass's sections are transparent BY DESIGN because they
   rely on the pane behind them, so the result was text on nothing.

   With two rails the answer is not to restore one panel but to give EACH RAIL ITS OWN. The left
   rail is a single card, so it becomes its own pane; the right rail is the `.swrap` wrapper,
   so the pane goes there and its cards stay transparent exactly as the design intends. */

/* GLASS — the frosted pane, once per rail. */
#px-d-grid.dl-dual-sidebar.ds-glass .rq-side > .side-card,
#px-d-grid.dl-dual-sidebar.ds-glass .rq-side > .swrap > .side-card{
  border-radius:18px!important;
  background:
    linear-gradient(168deg,
      color-mix(in srgb,var(--accent) 14%,var(--card)) 0%,
      color-mix(in srgb,var(--accent) 4%,var(--card)) 52%,
      color-mix(in srgb,var(--card) 94%,var(--ink)) 100%)!important;
  border:1px solid color-mix(in srgb,var(--accent) 20%,var(--line))!important;
  box-shadow:
    0 1px 2px color-mix(in srgb,var(--ink) 5%,transparent),
    0 10px 24px -6px color-mix(in srgb,var(--ink) 10%,transparent),
    inset 0 1px 0 color-mix(in srgb,var(--card) 92%,transparent)!important;
  overflow:hidden;
}
@supports (backdrop-filter:blur(1px)){
  #px-d-grid.dl-dual-sidebar.ds-glass .rq-side > .side-card,
  #px-d-grid.dl-dual-sidebar.ds-glass .rq-side > .swrap{backdrop-filter:blur(20px) saturate(1.45)}
}
/* inside a rail the sections stay transparent, and the rail's own ends carry the corners */


/* SLAB — same idea, its own material. */
#px-d-grid.dl-dual-sidebar.ds-slab .rq-side > .side-card,
#px-d-grid.dl-dual-sidebar.ds-slab .rq-side > .swrap > .side-card{
  border-radius:20px!important;
  background:
    linear-gradient(160deg,
      color-mix(in srgb,var(--accent) 13%,var(--card)) 0%,
      color-mix(in srgb,var(--accent) 5%,var(--card)) 46%,
      color-mix(in srgb,var(--card) 92%,var(--ink)) 100%)!important;
  border:1px solid color-mix(in srgb,var(--accent) 18%,var(--line))!important;
  box-shadow:
    0 1px 2px color-mix(in srgb,var(--ink) 5%,transparent),
    0 10px 24px -6px color-mix(in srgb,var(--ink) 10%,transparent),
    inset 0 1px 0 color-mix(in srgb,var(--card) 92%,transparent)!important;
  overflow:hidden;
}
@supports (backdrop-filter:blur(1px)){
  #px-d-grid.dl-dual-sidebar.ds-slab .rq-side > .side-card,
  #px-d-grid.dl-dual-sidebar.ds-slab .rq-side > .swrap{backdrop-filter:blur(20px) saturate(1.45)}
}


/* RAIL — it needs no pane (its cards carry their own surface), but each rail must READ as a
   complete spine: the single left card gets all four corners, and the right rail's ends close it. */
/* ⚠ :first-child IS NEEDED TO WIN. ds-rail's own `…> .side-card:first-child{border-radius:16px 16px
   0 0!important}` is one id + three classes + a pseudo-class; without the pseudo here the two tie
   and source order decides — measured, mine lost and the left rail kept a top-only radius. */
#px-d-grid.dl-dual-sidebar.ds-rail .rq-side > .side-card,
#px-d-grid.dl-dual-sidebar.ds-rail .rq-side > .side-card:first-child{border-radius:16px!important}
#px-d-grid.dl-dual-sidebar.ds-rail .rq-side > .swrap > .side-card,
#px-d-grid.dl-dual-sidebar.ds-rail .rq-side > .swrap > .side-card:first-child,
#px-d-grid.dl-dual-sidebar.ds-rail .rq-side > .swrap > .side-card:last-child{border-radius:16px!important}

/* ═══ LAYOUT 9 — THE EXECUTIVE READ ═══════════════════════════════════════════════════════════
   ⚠ THIS LAYOUT KEEPS ITS SIDEBAR. An earlier attempt dissolved `.rq-side` with `display:contents`
   and spread the cards into bands across the page — a summary strip on top, an appendix at the
   foot. It looked like a statement and it was wrong: with no sidebar COLUMN there is nothing for
   the six sidebar designs to dress, so rail, glass and slab had no surface and the operator's
   choice stopped meaning anything on this layout. Every layout carries a real sidebar; the six
   designs must work on all nine. This one is distinguished by its READING COLUMN alone.

   ⚠ IT WAS ALSO BROKEN BEFORE THAT. The original stub was `grid-template-columns:1fr` plus
   `.rq-side{order:2}` and a hardcoded slate shadow. The `1fr` lost to the sidebar-side setting on
   every render, so it drew as two columns with a card never laid out for one: the card was
   `display:grid`, putting the "Ticket information" heading and the field rows side by side at the
   same y (measured: 94 and 227) — overlapping.

   What makes it its own: the conversation is set as EDITORIAL COPY. One generous measure, no cards,
   no discs, no bubbles; entries divided by hairlines, the author in letterspaced small caps, a 2px
   rule naming the voice, and body text at 1.78 leading — set to be read rather than scanned. */

/* the column itself is ordinary, which is the point — dsp-* places it, ds-* dresses it */
#px-d-grid.dl-executive .thread{display:block;gap:0;max-width:760px;margin:0 auto}
#px-d-grid.dl-executive .thread .brow,
#px-d-grid.dl-executive .thread .brow.mine{
  display:block;width:100%;max-width:100%;margin:0;
  padding:26px 0 24px;flex-direction:row;
  border-top:1px solid color-mix(in srgb,var(--ink) 7%,transparent);
}
#px-d-grid.dl-executive .thread .brow:first-child{border-top:0}
#px-d-grid.dl-executive .thread .avat{display:none}   /* editorial copy names its voices, it does not badge them */
#px-d-grid.dl-executive .thread .bubble{
  width:100%;max-width:100%;margin:0;padding:0 0 0 20px;
  background:none!important;border:0!important;border-radius:0!important;box-shadow:none!important;
  border-left:2px solid color-mix(in srgb,var(--ink) 12%,transparent)!important;
  display:block;
}
#px-d-grid.dl-executive .thread .bubble::after{content:none}
#px-d-grid.dl-executive .thread .brow:not(.mine) .bubble{border-left-color:var(--accent)!important}
#px-d-grid.dl-executive .thread .brow.mine .bubble{border-left-color:color-mix(in srgb,var(--warn) 62%,transparent)!important}
#px-d-grid.dl-executive .thread .bubble > .who{
  display:block;margin:0 0 3px;
  font-size:10px;font-weight:800;letter-spacing:.2em;text-transform:uppercase;
}
#px-d-grid.dl-executive .thread .brow:not(.mine) .bubble > .who{color:var(--accent)}
#px-d-grid.dl-executive .thread .brow.mine .bubble > .who{color:color-mix(in srgb,var(--warn) 74%,var(--ink))}
#px-d-grid.dl-executive .thread .bubble > .at{
  display:block;margin:0 0 14px;
  font-size:10.5px;font-variant-numeric:tabular-nums;letter-spacing:.02em;
  color:color-mix(in srgb,var(--ink) 40%,transparent);
}
#px-d-grid.dl-executive .thread .bubble > .body{
  font-size:14.5px;line-height:1.78;letter-spacing:.002em;
  color:color-mix(in srgb,var(--ink) 92%,transparent);
}
#px-d-grid.dl-executive .thread .bubble > .rr{display:flex;justify-content:flex-start;margin-top:14px;gap:0;border:0;background:none}
#px-d-grid.dl-executive .thread .rr .rr-label{
  position:absolute;width:1px;height:1px;padding:0;margin:-1px;
  overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0;
}
#px-d-grid.dl-executive .thread .rr .rr-star{padding:0 2px;font-size:18px;line-height:1;background:none;border:0}
#px-d-grid.dl-executive .thread .bubble > .rx{display:flex;justify-content:flex-start;margin-top:10px}
#px-d-grid.dl-executive .thread .tsep{
  display:block;margin:0;padding:22px 0 0;border:0;background:none;text-align:center;
}
#px-d-grid.dl-executive .thread .tsep::before,
#px-d-grid.dl-executive .thread .tsep::after{content:none}
#px-d-grid.dl-executive .thread .tsep-chip{
  background:none;border:0;padding:0;border-radius:0;box-shadow:none;
  font-size:9.5px;font-weight:800;letter-spacing:.26em;text-transform:uppercase;
  color:color-mix(in srgb,var(--ink) 38%,transparent);
}
#px-d-grid.dl-executive #px-d-card{
  border-radius:18px;
  box-shadow:
    0 1px 2px color-mix(in srgb,var(--ink) 4%,transparent),
    0 18px 44px -30px color-mix(in srgb,var(--ink) 26%,transparent);
}

#px-d-grid.dl-tabs.dsp-left,
#px-d-grid.dl-tabs.dsp-right{grid-template-columns:1fr}

/* ── STICKY: THE COMPOSE MECHANISM ────────────────────────────────────────────────────────
   My first attempt made the whole column a sticky box with `max-height:100vh; overflow:auto`, so it
   scrolled INSIDE itself. That is not how this portal scrolls anywhere else, and it was wrong twice:
   it introduced an inner scroll area, and nesting the cards' own sticky inside a sticky parent held
   the first card 83px down from the top of its container — the blank tinted band above the heading.

   The compose page already had the right mechanism: `.side-card{position:sticky; top:navh+13px}`.
   Each card pins under the nav as you scroll and the content below travels over it. So that is what
   every design uses now — no inner scrollbar, no max-height, nothing to reach past.

   ⚠ THE OFFSET MUST RIDE --px-navh, never a hardcoded pixel: with a non-sticky nav it is 0 and a
   fixed 82px would float the cards down for no reason. */
/* ── The two modes, chosen by measurement in pxSideStickyMode() ───────────────────────────
   dss-fits — the set is shorter than the screen, so the whole column stays as one block. No card
              climbs over another and no empty space opens up beneath a lone pinned card.
   dss-tall — the set is taller than the screen, so cards pin in turn (the compose behaviour) and
              every one of them stays reachable. */
#px-d-grid.dss-sticky.dss-fits .rq-side{
  position:sticky;top:calc(var(--px-navh,0px) + 13px);align-self:start;
  max-height:none;
  /* ⚠ DO NOT SET overflow HERE. This selector carries one more class than #px-d-grid.ds-rail
     .rq-side, so a leftover `overflow:visible` from the abandoned internal-scroll approach beat the
     rail's own `overflow:hidden` — and the rail stopped clipping. The inner card has square corners
     (border-radius:0, by design, so the sections read as one surface), so unclipped they painted
     right into the rail's 18px curve: a visible notch at all four corners. Each design's own
     overflow now stands. */
}
#px-d-grid.dss-sticky.dss-fits .rq-side .side-card{position:static;top:auto}

#px-d-grid.dss-sticky.dss-tall .rq-side{
  position:static;                      /* the CARDS stick, not the column */
  max-height:none;                      /* overflow is the DESIGN's call — see the note above */
  /* ⚠ MUST STRETCH, NOT START. A sticky child can only travel inside its parent's box, and
     align-self:start shrinks this column to the height of its own cards — leaving them nowhere to
     go, so they scrolled straight off the top (measured: tops of -334, -333, -198, -128 at
     scrollY 1400) even though position:sticky was correctly applied. The compose page works
     precisely because its aside STRETCHES to the tall form row, giving the cards room to pin in. */
  align-self:stretch;
}
/* ── TALL: one shared offset, no stacking ─────────────────────────────────────────────────
   Two things were tried here and both rejected on sight: cumulative offsets piled the cards into a
   deck of overlapping headers, and an internal scroll area was not how anything else in this portal
   scrolls. The cards share ONE offset — the same rule the compose sidebar uses — so the ticket
   information pins under the nav and the rest travels past it. That card is what is left at the end
   of the scroll, which is the point of pinning it. */
/* ⚠ ONLY THE FIRST CARD PINS. Applying the sticky to every .side-card let the cards INSIDE
   .swrap pin within that wrapper's own tall box and ride over one another — "Related help"
   slid across "Your other tickets". The wrapper's children are explicitly static; the ticket
   information card, a direct child of the column, is the one that holds. */
/* ⚠ THE SECTIONS PASS IN FRONT OF THE PINNED CARD, NOT BEHIND IT. The ticket-information card
   holds at the nav while the sections below travel up past it. Sending them behind it hid them —
   "how are you supposed to use them? under hides them" — so the pinned card is the LOWER layer and
   each passing section scrolls over it and stays readable the whole way up.

   ⚠ z-index DOES NOTHING ON A STATIC BOX. The passing cards are explicitly `position:static`, so
   the `z-index:1` that used to sit on them was inert and the pinned card won on being positioned
   alone. The layer has to be established on the WRAPPER, which is positioned for that purpose. */
#px-d-grid.dss-sticky.dss-tall .rq-side > .side-card{
  position:sticky;
  top:calc(var(--px-navh,0px) + 13px);
  z-index:1;
}
#px-d-grid.dss-sticky.dss-tall .rq-side > .swrap{position:relative;z-index:5}
#px-d-grid.dss-sticky.dss-tall .rq-side > .swrap .side-card{position:static;top:auto}
/* ⚠ LEAVE THE WRAPPER ALONE. Cards 2..n live in .swrap, whose box is only as tall as they
   are, so they cannot pin — they travel past the pinned ticket-information card and are gone. That
   is the intended behaviour: ONE card holds, the rest scroll past it. Dissolving this wrapper with
   display:contents makes them all pin and slide under each other instead, which is not wanted. */
#px-d-grid.dss-sticky.dss-tall .rq-side > .swrap{display:flex;flex-direction:column;gap:14px}
#px-d-grid.dss-sticky.dss-tall .rq-side > .swrap > .side-card{margin-bottom:14px}
/* ⚠ NO BACKGROUND OVERRIDE HERE. This used to force an opaque surface on every side card so the
   pinned one could cover the passers. It also flattened the GLASSMORPHISM look pack's translucent
   cards with !important, which is not ours to override — the operator picked that look. The passing
   sections now travel in front, so nothing needs to be made opaque to hide anything. */

/* ── RAIL AND GLASS ARE ONE SURFACE ───────────────────────────────────────────────────────
   A card sliding around inside a continuous tinted panel would tear away from its own background,
   so for these two the SURFACE is the sticky unit and the cards inside stay put.

   ⚠ BOTH MODE CLASSES ARE REQUIRED IN THE SELECTOR. Written as `.dss-sticky.ds-rail` this tied with
   `.dss-sticky.dss-tall` — one id and two classes each — and lost on source order, so the rail
   inherited align-self:stretch and grew 2192px past its own last card as a giant empty tinted box.
   Naming the mode class too puts it one class ahead, which is what makes it hold. */
/* Rail and Glass keep the SAME pinning as every other design. Making the container the sticky unit
   and freezing the cards inside it is what killed the card-over-card scroll — the corner fix was
   not the culprit. Their seamless look is built from ADJACENT CARDS instead of from a container
   surface (below), so nothing needs to be frozen and nothing stretches. */

/* Not sticky at all: the cards sit where they are. */
#px-d-grid:not(.dss-sticky) .rq-side .side-card{position:static;top:auto}

@media (max-width:860px){
  /* Stacked: there is no second column to stick beside, and pinning a full-width block would
     cover the conversation. */
  #px-d-grid.dsp-left,
  #px-d-grid.dsp-right{grid-template-columns:minmax(0,1fr)}
  #px-d-grid.dss-sticky .rq-side{position:static;max-height:none;overflow:visible}
}

/* The information column's heading. Sized per design so it reads as that design's own header
   rather than a label dropped on top of it. */
#px-d-grid .rq-side .sd-title{
  display:flex;align-items:center;gap:9px;
  font-size:11px;font-weight:800;letter-spacing:.1em;text-transform:uppercase;
  color:var(--ink-3);margin:0 0 12px;
}
/* ── CARDS: the ticket heading matches the section headings ───────────────────────────────────
   The base rule above puts `.sd-title` at 11px in --ink-3 while `.smc-h` sits at 12.5px in --ink,
   so on the boxed set the PRIMARY heading rendered smaller AND lighter than the three sections
   beneath it — backwards, and the same fault already fixed on Stack. Matched here to 12.5px /
   --ink / .03em, which are `.smc-h`'s own values, so all four headings on the column agree.
   ⚠ SCOPED TO ds-cards ON PURPOSE. Rail inherits this same base and has the identical 11px, but it
   has already been reviewed and signed off at that size — changing the base would have moved it
   without being asked. Ledger and Glass set their own size and are unaffected either way. */
#px-d-grid.ds-cards .rq-side .sd-title{
  font-size:12.5px;letter-spacing:.03em;color:var(--ink);
}
/* The icon chip matches .smc-h on the other side cards, so the column reads as one set of
   sections rather than one titled list plus two titled cards. */
#px-d-grid .rq-side .sd-title .sd-title-ic{
  flex:0 0 auto;width:26px;height:26px;border-radius:8px;
  display:grid;place-items:center;
  background:color-mix(in srgb,var(--accent) 12%,transparent);
  color:var(--accent);
}
#px-d-grid .rq-side .sd-title .sd-title-ic svg{width:15px;height:15px}
#px-d-grid .rq-side .sd-title .sd-title-t{min-width:0}
#px-d-grid.ds-rail .rq-side .sd-title,
#px-d-grid.ds-glass .rq-side .sd-title{
  margin:-2px 0 12px;padding-bottom:11px;
  border-bottom:1px solid color-mix(in srgb,var(--ink) 9%,transparent);
  color:color-mix(in srgb,var(--ink) 62%,transparent);
}
#px-d-grid.ds-ledger .rq-side .sd-title{
  margin:0;padding:9px 12px;
  background:color-mix(in srgb,var(--ink) 4%,transparent);
  border-bottom:1px solid var(--line);font-size:10px;letter-spacing:.11em;
}

/* ⚠ NO SCROLLBAR on the sticky column — asked for explicitly. It still SCROLLS when it is taller
   than the screen; the bar is simply not painted, on every engine. */

/* ⚠ NESTED STICKY — THE CAUSE OF THE EMPTY BAND AND THE "CLIMBING" CARD.
   The first side-card carries its own `position:sticky; top:82px` from before this column could
   stick. Now that .rq-side is the sticky, scrolling container, that inner sticky does two visible
   things wrong: it holds the card 83px DOWN from the top of its own container — the blank tinted
   band above "Ticket information" — and it pins the card in place while the cards below scroll
   underneath it, so it climbs over them. The outer column owns the pinning now, so the cards inside
   must be static. */

/* ── ds-rail: STICKY AS ONE BLOCK, NEVER STACKING ─────────────────────────────────────────
   The column follows the reader down the page, but nothing pins card-over-card: the sections keep
   their order and their spacing, and the whole thing moves as one object. That is only safe because
   this design has NO tinted container to stretch — the spine and the surfaces live on the sections
   themselves — so `align-self:start` costs nothing here.
   Both mode classes are named so this outranks the generic sticky rules rather than relying on
   source order (one id + five classes against four). */
#px-d-grid.dss-sticky.dss-tall.ds-rail .rq-side,
#px-d-grid.dss-sticky.dss-fits.ds-rail .rq-side{
  position:sticky!important;
  top:calc(var(--px-navh,0px) + 14px)!important;
  align-self:start!important;
  gap:0!important;
}
#px-d-grid.dss-sticky.dss-tall.ds-rail .rq-side .side-card,
#px-d-grid.dss-sticky.dss-fits.ds-rail .rq-side .side-card{
  position:static!important;top:auto!important;margin:0!important;
}
/* ⚠ NO GAPS ANYWHERE, or the spine is a dashed line instead of a line. The sticky-mode rules set a
   14px gap and margin between side cards and outranked ds-rail's own `gap:0`. */
#px-d-grid.dss-sticky.dss-tall.ds-rail .rq-side > .swrap,
#px-d-grid.dss-sticky.dss-fits.ds-rail .rq-side > .swrap{
  gap:0!important;margin:0!important;border-top:0!important;
}

/* ── THE HEADER PANEL ──────────────────────────────────────────────────────────────────────
   ⚠ NOT A DARK PANEL. The first version mixed --ink down towards --bg to build a deep navy block.
   Every value came from a token, but the RESULT still ignored the configuration: this workspace's
   portal is light, and a dark slab is a design decision the operator never made. Respecting the
   configuration means looking like the operator's own surfaces, not deriving a new scheme from
   their tokens — so the panel is the CARD colour, lifted by the accent they chose, and the premium
   comes from the spine, the markers, the hairlines and the type rather than from an invented shade. */
#px-d-grid.ds-rail .rq-side > .side-card:first-child{
  background-color:var(--card)!important;
  background-image:
    radial-gradient(130% 100% at 0% 0%, color-mix(in srgb,var(--accent) 16%,transparent) 0%, transparent 58%),
    linear-gradient(180deg, color-mix(in srgb,var(--accent) 7%,var(--card)), var(--card))!important;
  padding:20px 20px 20px 26px;
  border-radius:16px 16px 0 0!important;
}
#px-d-grid.ds-rail .rq-side > .side-card:first-child .sd-title{
  color:var(--ink);letter-spacing:.09em;margin-bottom:14px;
}
#px-d-grid.ds-rail .rq-side > .side-card:first-child .sd-title .sd-title-ic{color:var(--accent)}
#px-d-grid.ds-rail .rq-side > .side-card:first-child .sd-title::before{
  background:var(--accent);
  /* the ring matches the surface it sits on */
  box-shadow:0 0 0 3px var(--card), 0 0 12px 2px color-mix(in srgb,var(--accent) 55%,transparent);
}
#px-d-grid.ds-rail .rq-side > .side-card:first-child #px-d-fields .sd-l{color:var(--ink-3)}
#px-d-grid.ds-rail .rq-side > .side-card:first-child #px-d-fields .sd-v{color:var(--ink);font-size:14px}
#px-d-grid.ds-rail .rq-side > .side-card:first-child #px-d-fields .sd-row + .sd-row{
  border-top:1px dashed color-mix(in srgb,var(--ink) 12%,transparent);
}
/* The action stays the operator's own accent surface. */
#px-d-grid.ds-rail .rq-side > .side-card:first-child #px-d-actions button{
  width:100%;border:0;
  background:var(--accent-bg,linear-gradient(135deg,var(--accent),color-mix(in srgb,var(--accent) 74%,var(--ink))))!important;
  color:var(--card)!important;
  box-shadow:0 10px 26px -10px color-mix(in srgb,var(--accent) 70%,transparent);
  padding:13px 18px;font-weight:800;
}
/* The spine is brightest at the header and fades down the column. */
#px-d-grid.ds-rail .rq-side > .side-card:first-child::before{
  width:4px;
  background:linear-gradient(180deg,var(--accent),color-mix(in srgb,var(--accent) 40%,transparent));
  box-shadow:0 0 14px 1px color-mix(in srgb,var(--accent) 45%,transparent);
}

/* ── ds-rail — PREMIUM PASS: depth, glass, hover, motion. Not one colour literal. ──────────
   Everything below composes from --accent / --ink / --card / --bg / --line, so a change of accent
   or a switch to dark mode carries the whole treatment with it instead of breaking it. */

/* Frosted body sections: the page shows faintly through, which is what separates this from the
   flat Cards design without adding another box. */
#px-d-grid.ds-rail .rq-side > .swrap > .side-card{
  background-color:color-mix(in srgb,var(--card) 76%,transparent)!important;
  background-image:linear-gradient(90deg,
    color-mix(in srgb,var(--accent) 7%,transparent) 0,
    transparent 140px)!important;
}
@supports (backdrop-filter:blur(1px)){
  #px-d-grid.ds-rail .rq-side > .swrap > .side-card{backdrop-filter:blur(10px) saturate(1.25)}
}

/* The whole column reads as one raised object, lit from the accent side. */
#px-d-grid.ds-rail .rq-side{
  filter:drop-shadow(0 22px 40px color-mix(in srgb,var(--ink) 16%,transparent));
}

/* HOVER — a section lifts its own tint and brightens its spine segment. */
#px-d-grid.ds-rail .rq-side .side-card{
  transition:background-color .18s var(--ease,ease), background-image .18s var(--ease,ease);
}
#px-d-grid.ds-rail .rq-side > .swrap > .side-card:hover{
  background-color:color-mix(in srgb,var(--card) 92%,transparent)!important;
}
#px-d-grid.ds-rail .rq-side .side-card::before{transition:box-shadow .2s var(--ease,ease), width .16s var(--ease,ease)}
#px-d-grid.ds-rail .rq-side .side-card:hover::before{
  width:4px;
  box-shadow:0 0 14px 1px color-mix(in srgb,var(--accent) 55%,transparent);
}

/* Rows and links: an accent wash slides in from the spine on hover, so the eye tracks the edge. */
#px-d-grid.ds-rail #px-d-fields .sd-row{
  margin-inline:-8px;padding-inline:8px;border-radius:7px;
  transition:background .16s var(--ease,ease);
}
#px-d-grid.ds-rail #px-d-fields .sd-row:hover{
  background:linear-gradient(90deg,color-mix(in srgb,var(--accent) 14%,transparent),transparent);
}
#px-d-grid.ds-rail .smc-item{
  margin-inline:-8px;padding:8px;border-radius:8px;
  transition:background .16s var(--ease,ease), translate .16s var(--ease,ease);
}
#px-d-grid.ds-rail .smc-item:hover{
  background:linear-gradient(90deg,color-mix(in srgb,var(--accent) 12%,transparent),transparent);
  translate:2px 0;
}
/* The marker brightens with its section. */
#px-d-grid.ds-rail .rq-side .smc-h::before{transition:box-shadow .2s var(--ease,ease)}
#px-d-grid.ds-rail .rq-side > .swrap > .side-card:hover .smc-h::before{
  box-shadow:0 0 0 3px var(--card), 0 0 12px 2px color-mix(in srgb,var(--accent) 60%,transparent);
}
/* The panel's action lifts on hover, and presses in. */
#px-d-grid.ds-rail .rq-side > .side-card:first-child #px-d-actions button{
  transition:transform .15s var(--ease,ease), box-shadow .18s var(--ease,ease);
}
#px-d-grid.ds-rail .rq-side > .side-card:first-child #px-d-actions button:hover{
  transform:translateY(-1px);
  box-shadow:0 16px 34px -12px color-mix(in srgb,var(--accent) 95%,transparent);
}
#px-d-grid.ds-rail .rq-side > .side-card:first-child #px-d-actions button:active{transform:translateY(0) scale(.99)}

@media(prefers-reduced-motion:reduce){
  #px-d-grid.ds-rail .rq-side *,
  #px-d-grid.ds-rail .rq-side *::before{transition:none!important}
  #px-d-grid.ds-rail .smc-item:hover{translate:none}
}

/* ═══ THE SUPPORT RAIL — FROSTED ══════════════════════════════════════════════════════════════
   The default rail style ("plain") was the flattest surface in the portal: white rows on a white
   card with no edge, no depth and a wash on hover. It is also the one most operators will never
   change, so the default is what should carry the craft.

   This frosts the whole rail — a translucent pane with a lit top edge and a soft cast shadow —
   and turns each link into its own glass chip that lifts and takes the accent as the cursor
   crosses it. The heading gains a headset mark and a hairline beneath it.

   ⚠ SCOPED TO THE DEFAULT ONLY (`.dp-rail:not(.rs-tiles):not(.rs-stack):not(.rs-identity)
   :not(.rs-icons):not(.rs-console)`). The five named rail styles are operator choices that have
   already been signed off; none of them may be touched by this.
   ⚠ ALL COLOUR IS color-mix ON --accent / --ink / --card / --line, so the frost follows the
   configured palette in light or dark. No literals. */

#px-d-rail-scope,
.dp-rail:not(.rs-tiles):not(.rs-stack):not(.rs-identity):not(.rs-icons):not(.rs-console){
  border-radius:18px;
  background:linear-gradient(168deg,
    color-mix(in srgb,var(--accent) 7%,var(--card)),
    color-mix(in srgb,var(--card) 96%,var(--ink)));
  border:1px solid color-mix(in srgb,var(--accent) 14%,var(--line));
  box-shadow:
    inset 0 1px 0 color-mix(in srgb,var(--card) 92%,transparent),
    0 1px 2px color-mix(in srgb,var(--ink) 4%,transparent),
    0 18px 44px -30px color-mix(in srgb,var(--ink) 30%,transparent);
}
@supports (backdrop-filter:blur(1px)){
  .dp-rail:not(.rs-tiles):not(.rs-stack):not(.rs-identity):not(.rs-icons):not(.rs-console){
    backdrop-filter:blur(18px) saturate(1.4);
  }
}

/* ── THE HEADING ── mark, words, hairline. */
.dp-rail .dp-rail-title{
  display:flex;align-items:center;gap:9px;
  padding-bottom:13px;margin-bottom:13px;
  border-bottom:1px solid color-mix(in srgb,var(--ink) 9%,transparent);
}
.dp-rail .dp-rail-title{
  font-size:17px;letter-spacing:-.01em;
}
.dp-rail .dp-rail-title .dprt-ic{
  flex:0 0 auto;color:var(--accent);
}
.dp-rail .dp-rail-title .dprt-t{min-width:0}

/* ── THE LINKS ── each one its own chip of glass. */
.dp-rail:not(.rs-tiles):not(.rs-stack):not(.rs-identity):not(.rs-icons):not(.rs-console) .dp-rail-link{
  margin-bottom:7px;
  border-radius:11px;
  background:color-mix(in srgb,var(--card) 62%,transparent);
  border:1px solid color-mix(in srgb,var(--ink) 7%,transparent);
  box-shadow:
    inset 0 1px 0 color-mix(in srgb,var(--card) 94%,transparent),
    0 1px 2px color-mix(in srgb,var(--ink) 4%,transparent);
  transition:background .18s var(--ease,ease), box-shadow .18s var(--ease,ease),
             border-color .18s var(--ease,ease), transform .18s var(--ease,ease);
}
.dp-rail:not(.rs-tiles):not(.rs-stack):not(.rs-identity):not(.rs-icons):not(.rs-console) .dp-rail-link:hover{
  background:var(--card);
  border-color:color-mix(in srgb,var(--accent) 34%,var(--line));
  transform:translateY(-1px);
  box-shadow:
    inset 0 1px 0 color-mix(in srgb,var(--card) 96%,transparent),
    0 2px 4px color-mix(in srgb,var(--ink) 5%,transparent),
    0 10px 22px -12px color-mix(in srgb,var(--accent) 46%,transparent);
}
/* the primary action reads as the one solid object on a frosted rail */
.dp-rail:not(.rs-tiles):not(.rs-stack):not(.rs-identity):not(.rs-icons):not(.rs-console) .dp-rail-link.dp-rail-cta{
  background:var(--accent-bg,linear-gradient(135deg,var(--accent),var(--accent-d,var(--accent))));
  border-color:color-mix(in srgb,var(--card) 30%,var(--accent));
  box-shadow:
    inset 0 1px 0 color-mix(in srgb,var(--card) 44%,transparent),
    0 2px 5px color-mix(in srgb,var(--accent) 24%,transparent),
    0 12px 26px -12px color-mix(in srgb,var(--accent) 55%,transparent);
}
.dp-rail:not(.rs-tiles):not(.rs-stack):not(.rs-identity):not(.rs-icons):not(.rs-console) .dp-rail-link.dp-rail-cta:hover{
  transform:translateY(-1px);
  box-shadow:
    inset 0 1px 0 color-mix(in srgb,var(--card) 52%,transparent),
    0 3px 7px color-mix(in srgb,var(--accent) 28%,transparent),
    0 18px 34px -14px color-mix(in srgb,var(--accent) 70%,transparent);
}

/* ── THE HOURS CARD ── the same material, so the rail reads as one surface. */
.dp-rail:not(.rs-tiles):not(.rs-stack):not(.rs-identity):not(.rs-icons):not(.rs-console) .dp-hours{
  margin-top:14px;padding-top:14px;
  border-top:1px solid color-mix(in srgb,var(--ink) 9%,transparent);
}
.dp-rail:not(.rs-tiles):not(.rs-stack):not(.rs-identity):not(.rs-icons):not(.rs-console) .dph-body .dph-row{
  border-radius:10px;
  background:color-mix(in srgb,var(--card) 55%,transparent);
  border:1px solid color-mix(in srgb,var(--ink) 6%,transparent);
}
.dp-rail:not(.rs-tiles):not(.rs-stack):not(.rs-identity):not(.rs-icons):not(.rs-console) .dph-body .dph-row.is-today{
  background:color-mix(in srgb,var(--accent) 12%,var(--card));
  border-color:color-mix(in srgb,var(--accent) 28%,var(--line));
  box-shadow:inset 0 1px 0 color-mix(in srgb,var(--card) 88%,transparent);
}

@media(prefers-reduced-motion:reduce){
  .dp-rail .dp-rail-link:hover{transform:none}
}

/* ═══ F4 — new sidebar designs (detail ds-*, rail rs-*) ═══ */
/* DOSSIER — the F500 case file: monospace field labels, dense hairline rows. */
#px-d-grid.ds-dossier .rq-side .side-card{border:1px solid var(--line);border-radius:4px;box-shadow:none;background:var(--card)}
#px-d-grid.ds-dossier .rq-side .side-card + .side-card{margin-top:10px}
#px-d-grid.ds-dossier .rq-side .sd-head{font:800 10.5px/1 ui-monospace,Menlo,Consolas,monospace;letter-spacing:.14em;text-transform:uppercase;color:var(--ink-3);border-bottom:1px solid var(--line);padding-bottom:8px}
#px-d-grid.ds-dossier .rq-side .side-card > div:not(.sd-head){border-bottom:1px solid var(--line-soft);padding:7px 0;font-size:12.5px}
#px-d-grid.ds-dossier .rq-side .side-card > div:last-child{border-bottom:0}
/* TIMELINE — activity-first: a vertical guideline threads the cards. */
#px-d-grid.ds-timeline .rq-side{position:relative;padding-inline-start:18px}
#px-d-grid.ds-timeline .rq-side::before{content:"";position:absolute;inset-block:6px;inset-inline-start:5px;width:2px;border-radius:2px;background:linear-gradient(180deg,var(--accent),var(--line) 80%)}
#px-d-grid.ds-timeline .rq-side .side-card{position:relative;border:1px solid var(--line);border-radius:12px;background:var(--card)}
#px-d-grid.ds-timeline .rq-side .side-card::before{content:"";position:absolute;inset-inline-start:-17px;top:18px;width:8px;height:8px;border-radius:50%;background:var(--accent);box-shadow:0 0 0 3px color-mix(in srgb,var(--accent) 20%,transparent)}
#px-d-grid.ds-timeline .rq-side .side-card + .side-card{margin-top:14px}
/* ORBIT — detached floating mini-cards, weightless spacing. */
#px-d-grid.ds-orbit .rq-side{display:flex;flex-direction:column;gap:16px}
#px-d-grid.ds-orbit .rq-side .side-card{border:0;border-radius:18px;background:color-mix(in srgb,var(--card) 85%,transparent);backdrop-filter:blur(8px);box-shadow:0 14px 34px -18px color-mix(in srgb,var(--accent) 35%,rgba(15,23,42,.35));transition:transform .22s ease}
#px-d-grid.ds-orbit .rq-side .side-card:hover{transform:translateY(-3px)}
@media(prefers-reduced-motion:reduce){#px-d-grid.ds-orbit .rq-side .side-card{transition:none}#px-d-grid.ds-orbit .rq-side .side-card:hover{transform:none}}
/* CONCIERGE rail — a guided welcome: tinted header seat, roomy guided links. */
.rs-concierge .dp-rail-in > *:first-child, .rs-concierge > *:first-child{border-radius:14px}
.rs-concierge{background:linear-gradient(180deg,color-mix(in srgb,var(--accent) 7%,var(--card)),var(--card) 40%);border:1px solid color-mix(in srgb,var(--accent) 18%,var(--line));border-radius:16px;padding:16px}
.rs-concierge a{display:block;padding:11px 12px;border-radius:11px;font-weight:700}
.rs-concierge a:hover{background:color-mix(in srgb,var(--accent) 8%,transparent)}
/* DIRECTORY rail — grouped hairline sections, index feel. */
.rs-directory{border:1px solid var(--line);border-radius:14px;overflow:hidden;padding:0}
.rs-directory a{display:block;padding:11px 16px;border-top:1px solid var(--line-soft);font-size:13px}
.rs-directory a:first-child{border-top:0}
.rs-directory a:hover{background:var(--line-soft)}
/* MINIMAL rail — quiet text list, zero chrome. */
.rs-minimal{border:0;background:transparent;box-shadow:none;padding:4px 0}
.rs-minimal a{display:block;padding:7px 0;color:var(--ink-2);font-size:13px;border:0}
.rs-minimal a:hover{color:var(--accent)}
