/* Design tokens. Apple's system stack first: on macOS/iOS this resolves to SF Pro and the UI reads
   as native; elsewhere it falls back to Segoe UI / Noto. Chinese is given an explicit face so the
   mixed Latin/Chinese lines share a baseline instead of jumping between two unrelated fonts. */
:root {
  --font-ui: -apple-system, BlinkMacSystemFont, "SF Pro Text", "Segoe UI Variable Text", "Segoe UI",
             "PingFang TC", "Noto Sans TC", "Microsoft JhengHei", sans-serif;
  /* One blue-green family, varied along the blue↔green axis so the four field groups stay tellable
     apart without introducing a second hue. Red is kept because it is semantic, not decorative:
     errors must not read as just another group colour. */
  --accent: #0a7c8a; --accent-strong: #06626e; --accent-soft: #e4f2f4;
  --teal-blue: #1b7fa8;  /* 基本條件 */
  --teal-green: #128a6a; /* 連結標的 */
  --teal-core: #0a7c8a;  /* 收益條件 */
  --teal-deep: #2a6f78;  /* 風險與交割 */
  --tint-red: #d1352b;
  /* Grouped-background hierarchy: the page sits behind, cards sit on top. */
  --bg-grouped: #f2f2f7; --bg-elevated: #ffffff; --bg-inset: #f7f7fa;
  --label: #1c1c1e; --label-2: #3c3c43bf; --label-3: #3c3c434d;
  --separator: #3c3c432e; --separator-solid: #d8d8dd;
  /* Apple's radii grow with the surface: controls 10, cards 14, sheets 20. */
  --r-control: 10px; --r-card: 14px; --r-sheet: 20px; --r-pill: 999px;
  --shadow-1: 0 1px 2px #0000000d, 0 1px 3px #0000000a;
  --shadow-2: 0 4px 12px #0000000f, 0 1px 3px #0000000a;
  --shadow-3: 0 12px 32px #00000014, 0 2px 8px #0000000d;
  --ease: cubic-bezier(.32,.72,0,1);
  /* Text styles, not sizes. SwiftUI's typographic discipline is that you pick a role and never a
     number; this file used to hold 49 ad-hoc values across 102 declarations. Values are Apple's
     text styles at the default content size, expressed in rem so they scale with the browser's
     font-size setting — the web's equivalent of Dynamic Type. Never add a bare px font-size:
     it silently opts that text out of user text scaling.
     Deliberately NOT applied to `.download-*`, `.quote-sheet*` and `.quote-card*`: those are
     fixed-canvas html2canvas render targets, and a responsive scale would change a PNG that has
     already been sent to a client. */
  --text-largetitle: 2.125rem;  /* 34 */
  --text-title:      1.75rem;   /* 28 */
  --text-title2:     1.375rem;  /* 22 */
  --text-title3:     1.25rem;   /* 20 */
  --text-headline:   1.0625rem; /* 17, pair with 600-650 weight */
  --text-body:       1.0625rem; /* 17 */
  --text-callout:    1rem;      /* 16 */
  --text-subheadline:.9375rem;  /* 15 */
  --text-footnote:   .8125rem;  /* 13 */
  --text-caption:    .75rem;    /* 12 */
  --text-caption2:   .6875rem;  /* 11 */
  /* 4pt rhythm, 8 as the common step. This file had 100 distinct padding declarations and no
     scale behind any of them. */
  --sp-1: 4px; --sp-2: 8px; --sp-3: 12px; --sp-4: 16px;
  --sp-5: 20px; --sp-6: 24px; --sp-7: 32px; --sp-8: 40px;
  /* 44 is the HIG minimum touch target and is not negotiable on phone or tablet. */
  --tap-min: 44px;
  font-family: var(--font-ui); color: var(--label);
  background: var(--bg-grouped);
  -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale;
  font-synthesis-weight: none;
}
* { box-sizing:border-box; }
body { margin:0; min-width:320px; }
button,input,select { font:inherit; }
.app-shell { max-width:1440px; margin:auto; padding:28px; }
.hero { display:flex; justify-content:space-between; gap:24px; align-items:center; position:relative; overflow:hidden; color:#fff; background:linear-gradient(135deg,#0b6b7a,#0a7c8a 55%,#0c7e8d); padding:30px 32px; border:0; border-radius:var(--r-sheet); box-shadow:var(--shadow-2); }.hero::after { content:""; position:absolute; width:280px; height:280px; right:-100px; top:-160px; border:44px solid #ffffff1a; border-radius:50%; }.hero > * { position:relative; z-index:1; }.hero h1 { margin:4px 0 8px; font-size:clamp(1.75rem,3vw,2.5rem); font-weight:700; letter-spacing:-.02em; line-height:1.15; }.hero p { max-width:620px; margin:0; color:#fff; line-height:1.55; }/* Used on both the dark hero and light cards, so the base colour must stay legible on white and
   only the hero overrides it. Getting this wrong makes the label vanish rather than look wrong. */
.eyebrow{ color:var(--label-2); font-size:var(--text-caption2); letter-spacing:.08em; font-weight:600; text-transform:uppercase; }.hero .eyebrow { color:#ffffffb8; }.quote-count { white-space:nowrap; padding:13px 19px; border:0; border-radius:var(--r-card); background:#ffffff26; backdrop-filter:blur(20px) saturate(180%); -webkit-backdrop-filter:blur(20px) saturate(180%); }.quote-count strong{ font-size:var(--text-title2); }
.market-holiday-alert{margin:var(--sp-4) 0;padding:var(--sp-5);border:2px solid #d97706;border-radius:var(--r-sheet);background:linear-gradient(135deg,#fff8e8,#fffdf7);color:#43240b;box-shadow:0 8px 24px #8a4b0d1f}.market-holiday-heading{display:flex;align-items:center;gap:var(--sp-3)}.market-holiday-heading h2{margin:2px 0 0;font-size:var(--text-title2);line-height:1.2}.market-holiday-heading .eyebrow{margin:0;color:#8b4a08}.market-holiday-icon{display:grid;flex:0 0 var(--tap-min);width:var(--tap-min);height:var(--tap-min);place-items:center;border-radius:var(--r-pill);background:#b45309;color:#fff;font-size:var(--text-title2);font-weight:800}.market-holiday-date{margin-left:auto;padding:var(--sp-2) var(--sp-3);border-radius:var(--r-pill);background:#9f2d20;color:#fff;font-size:var(--text-subheadline);white-space:nowrap}.market-holiday-priority{margin:var(--sp-4) 0 var(--sp-3);padding:var(--sp-3) var(--sp-4);border-radius:var(--r-control);background:#9f2d20;color:#fff;font-size:var(--text-headline);line-height:1.45}.market-holiday-alert ul{display:grid;gap:var(--sp-2);margin:0;padding-left:1.4em;line-height:1.55}.market-holiday-alert li::marker{color:#b45309}@media(max-width:760px){.market-holiday-alert{padding:var(--sp-4)}.market-holiday-heading{align-items:flex-start;flex-wrap:wrap}.market-holiday-date{width:100%;margin-left:0;text-align:center;white-space:normal}.market-holiday-priority{font-size:var(--text-body)}}
.notice { margin:16px 0; padding:13px 16px; background:var(--bg-elevated); border:0; border-left:4px solid var(--accent); border-radius:var(--r-card); color:var(--label); line-height:1.55; box-shadow:var(--shadow-1); }.link-button { border:0; background:none; color:var(--accent); text-decoration:none; cursor:pointer; padding:0 3px; font-weight:600; }@media (hover:hover) and (pointer:fine){.link-button:hover{ text-decoration:underline; }}
.toolbar { display:flex; flex-wrap:wrap; align-items:center; gap:9px; margin:0 0 14px; padding:11px; background:var(--bg-elevated); border:0; border-radius:var(--r-card); box-shadow:var(--shadow-1); }
/* iOS control hierarchy: filled for the primary action, tinted for secondary, plain for the rest.
   44px is Apple's minimum touch target and is kept on every pointer type, not just touch. */
.toolbar button,.guide-link { min-height:44px; border-radius:var(--r-control); border:0; padding:10px 16px; cursor:pointer; font-weight:600; letter-spacing:-.01em; transition:background .2s var(--ease),transform .12s var(--ease),box-shadow .2s var(--ease); }
.toolbar button:active,.guide-link:active { transform:scale(.97); }
.primary { background:var(--accent); color:#fff; box-shadow:none; }@media (hover:hover) and (pointer:fine){.primary:hover{ background:var(--accent-strong); }}
.secondary { background:var(--accent-soft); color:var(--accent-strong); border:0 !important; }@media (hover:hover) and (pointer:fine){.secondary:hover{ background:#d6ecee; }}
.danger { background:#d1352b17; color:#a82a22; border:0 !important; }@media (hover:hover) and (pointer:fine){.danger:hover{ background:#d1352b26; }}.guide-link { display:inline-flex; align-items:center; justify-content:center; text-decoration:none; background:var(--accent-soft); color:var(--accent-strong); }@media (hover:hover) and (pointer:fine){.guide-link:hover{ background:#d6ecee; }}.quote-image-button { background:var(--teal-blue); color:#fff; box-shadow:none; }@media (hover:hover) and (pointer:fine){.quote-image-button:hover{ background:#146382; }}.quote-image-button:disabled { cursor:wait; opacity:.75; }.quote-image-button.is-loading::before { content:""; display:inline-block; width:.85em; height:.85em; margin-right:.5em; border:2px solid #fff8; border-top-color:#fff; border-radius:50%; vertical-align:-.1em; animation:spin .7s linear infinite; } @keyframes spin { to { transform:rotate(360deg); } }.manual-email-button { background:#1b7fa81f; color:#146382; box-shadow:none; }@media (hover:hover) and (pointer:fine){.manual-email-button:hover{ background:#1b7fa833; }}.status { min-height:1.35rem; margin:0 2px 12px; color:var(--tint-red); font-weight:600; }.status.success { color:#0e6e54; }
.entry-workspace { margin-top:16px; padding:20px; border:0; border-radius:var(--r-sheet); background:var(--bg-elevated); box-shadow:var(--shadow-1); }.entry-workspace-header { display:flex; justify-content:space-between; align-items:end; gap:22px; margin:0 2px 16px; }.entry-workspace-header h2{ margin:4px 0 5px; color:var(--label); font-size:var(--text-title2); font-weight:700; letter-spacing:-.02em; }.entry-workspace-header p:not(.eyebrow) { margin:0; color:var(--label-2); line-height:1.5; }.field-group-legend { display:flex; flex-wrap:wrap; justify-content:flex-end; gap:6px; }.field-group-legend span{ padding:5px 11px; border-radius:var(--r-pill); font-size:var(--text-caption); font-weight:600; }.legend-basic { background:#1b7fa81f; color:#146382; }.legend-underlying { background:#128a6a1f; color:#0e6e54; }.legend-payoff { background:#0a7c8a1f; color:#07616c; }.legend-risk { background:#2a6f781f; color:#22585f; }
.trade-navigator { display:none; }
.table-card { overflow:visible; background:transparent; }.table-scroll { overflow:visible; -webkit-overflow-scrolling:touch; } #quoteTable { display:block; width:100%; min-width:0; border-collapse:separate; border-spacing:0; } #quoteTable thead { display:none; } #quoteTable tbody { display:grid; gap:18px; } #quoteTable tr { position:relative; display:grid; grid-template-columns:repeat(12,minmax(0,1fr)); gap:12px; padding:49px 16px 16px; border:0; border-radius:var(--r-card); background:var(--bg-elevated); box-shadow:var(--shadow-1); } #quoteTable td { min-width:0; padding:0; border:0; background:transparent; } #quoteTable .row-number{ position:absolute; top:0; left:0; display:flex; align-items:center; min-width:54px; height:35px; padding:0 15px; border-radius:var(--r-card) 0 12px 0; background:var(--accent); color:#fff; font-weight:600; font-size:var(--text-subheadline); } #quoteTable .quote-field { grid-column:span 2; } #quoteTable .quote-field[data-field="product"],#quoteTable .quote-field[data-field="currency"],#quoteTable .quote-field[data-field="tradeDate"],#quoteTable .quote-field[data-field="tenor"] { grid-column:span 3; } #quoteTable .quote-field[data-field="bbgCode1"] { grid-column:span 4; } #quoteTable .quote-field[data-field="bbgCode2"],#quoteTable .quote-field[data-field="bbgCode3"],#quoteTable .quote-field[data-field="bbgCode4"],#quoteTable .quote-field[data-field="bbgCode5"] { grid-column:span 2; } #quoteTable .quote-field[data-field="strike"],#quoteTable .quote-field[data-field="koBarrier"],#quoteTable .quote-field[data-field="coupon"],#quoteTable .quote-field[data-field="upfront"] { grid-column:span 2; } #quoteTable .quote-field[data-field="koType"] { grid-column:span 4; } /* Field groups are distinguished by a tinted inset surface rather than a coloured top rule: the
   grouping stays legible without four competing accent lines on one card. */
#quoteTable .field-label { display:grid; gap:5px; min-height:78px; padding:10px; border:0; border-radius:var(--r-control); background:#1b7fa814; } #quoteTable .group-underlying .field-label { background:#128a6a16; } #quoteTable .group-payoff .field-label { background:#0a7c8a14; } #quoteTable .group-risk .field-label { background:#2a6f7814; } #quoteTable .field-label-text{ color:var(--label-2); font-size:var(--text-caption); font-weight:600; line-height:1.2; } #quoteTable input,#quoteTable select { width:100%; min-width:0; min-height:40px; padding:7px 10px; border:1px solid var(--separator-solid); border-radius:8px; background:var(--bg-elevated); color:var(--label); transition:border-color .15s var(--ease),box-shadow .15s var(--ease); } #quoteTable input[readonly] { background:var(--bg-inset); color:var(--label-2); } #quoteTable input:focus,#quoteTable select:focus { outline:0; border-color:var(--accent); box-shadow:0 0 0 3.5px #0a7c8a2e; } .invalid { border-color:var(--tint-red) !important; box-shadow:0 0 0 3.5px #d1352b26 !important; background:#fff !important; }
dialog { max-width:560px; width:calc(100% - 32px); padding:20px; border:0; border-radius:var(--r-sheet); background:var(--bg-elevated); box-shadow:var(--shadow-3); }
dialog::backdrop { background:#00000052; backdrop-filter:blur(12px) saturate(140%); -webkit-backdrop-filter:blur(12px) saturate(140%); }
.dialog-content { padding:0; line-height:1.6; }.dialog-content h2 { margin-top:0; font-weight:700; letter-spacing:-.02em; }.dialog-content li{margin:8px 0}
/* Buttons placed directly in a dialog rather than in .dialog-actions were left at the browser
   default size, well under the 44px target the rest of the UI keeps. */
dialog button { min-height:44px; border:0; border-radius:var(--r-control); padding:10px 18px; cursor:pointer; font-weight:600; background:var(--accent-soft); color:var(--accent-strong); transition:background .2s var(--ease),transform .12s var(--ease); }
dialog button:active { transform:scale(.97); }
dialog button.primary { background:var(--accent); color:#fff; }
@media (hover:hover) and (pointer:fine){dialog button.primary:hover{ background:var(--accent-strong); }}
.issuer-dialog { max-width:430px; }.issuer-dialog label { display:block; margin:14px 0 6px; font-weight:600; color:var(--label-2); }.issuer-dialog select { width:100%; min-height:44px; padding:10px 12px; border:1px solid var(--separator-solid); border-radius:var(--r-control); background:var(--bg-elevated); color:var(--label); }.issuer-warning { margin:12px 0 0; padding:11px 13px; border-radius:var(--r-control); background:#d1352b14; color:#a82a22; font-weight:600; }.dialog-hint{ margin:12px 0 0; padding:11px 13px; border-radius:var(--r-control); background:var(--accent-soft); color:var(--accent-strong); font-size:var(--text-subheadline); }.dialog-actions { display:flex; justify-content:flex-end; gap:9px; margin-top:20px; }.dialog-actions button { min-height:44px; border-radius:var(--r-control); border:0; padding:10px 18px; cursor:pointer; font-weight:600; background:var(--accent-soft); color:var(--accent-strong); transition:background .2s var(--ease),transform .12s var(--ease); }.dialog-actions button:active { transform:scale(.97); }.dialog-actions button.primary { background:var(--accent); color:#fff; }
.email-clipboard-status { margin:12px 0; padding:10px; border-radius:7px; background:#e8f7f2; color:#12664f; font-weight:700; }.email-clipboard-status[data-state="none"],.email-clipboard-status[data-state="error"] { background:#fff1ed; color:#a3361d; }.email-compose-actions { display:grid; gap:10px; margin-top:14px; }.email-compose-actions label { margin:2px 0 0; }.email-compose-actions input { width:100%; min-height:42px; }.email-compose-actions small { color:#526778; line-height:1.55; }.email-compose-actions button { min-height:42px; border-radius:8px; padding:8px 14px; cursor:pointer; font-weight:bold; }
.quote-preview-panel { margin-top:26px; padding:22px; border:1px solid #d5e1e7; border-radius:14px; background:#e9f1f5; }.preview-heading { display:flex; align-items:end; justify-content:space-between; gap:20px; margin-bottom:16px; }.preview-heading h2 { margin:2px 0 0; color:#073b5c; }.preview-heading p { margin:0; color:#52616b; }.preview-actions { display:flex; align-items:center; justify-content:flex-end; gap:14px; }.preview-issuer-button { min-height:42px; padding:9px 14px; border-radius:8px; cursor:pointer; font-weight:bold; white-space:nowrap; }.quote-capture-scroll { overflow:auto; border-radius:10px; box-shadow:0 8px 22px #173c5020; }.quote-sheet { --issuer-color:#00776d; --issuer-accent:#0a6ea8; --issuer-soft:#eaf8f5; width:1400px; min-height:750px; padding:38px; background:linear-gradient(145deg,#edf9f8 0,#ffffff 32%,#eff7fb 100%); color:#16313d; font-family:Arial,"Microsoft JhengHei",sans-serif; }.quote-sheet.theme-bnp { --issuer-color:#008a4b; --issuer-accent:#0875a8; --issuer-soft:#e7f8ef; }.quote-sheet.theme-barclays { --issuer-color:#0077a8; --issuer-accent:#008b73; --issuer-soft:#e7f6fb; }.quote-sheet.theme-ms { --issuer-color:#006f80; --issuer-accent:#00855d; --issuer-soft:#e5f7f6; }.quote-sheet.theme-jpm { --issuer-color:#174d85; --issuer-accent:#00806c; --issuer-soft:#e8f3fb; }.quote-sheet.theme-nomura { --issuer-color:#b51f36; --issuer-accent:#7d1730; --issuer-soft:#fbecee; }.quote-sheet.theme-ubs { --issuer-color:#d71920; --issuer-accent:#8b1d33; --issuer-soft:#fcebed; }.quote-sheet.theme-dbs { --issuer-color:#d31245; --issuer-accent:#9e1638; --issuer-soft:#fbe9ef; }.quote-sheet.theme-sg { --issuer-color:#0875b9; --issuer-accent:#008a73; --issuer-soft:#e8f5fb; }.quote-sheet.theme-citi { --issuer-color:#056dae; --issuer-accent:#d23449; --issuer-soft:#e9f4fb; }.quote-sheet.theme-gs { --issuer-color:#1f6fb2; --issuer-accent:#16866c; --issuer-soft:#e9f4fb; }.quote-sheet.theme-ca { --issuer-color:#1b5aa6; --issuer-accent:#168064; --issuer-soft:#e9f1fb; }.quote-sheet-header { display:flex; align-items:center; justify-content:space-between; padding:0 0 24px; border-bottom:5px solid var(--issuer-color); }.quote-sheet-header p { margin:0 0 5px; color:#246075; font-size:14px; font-weight:bold; letter-spacing:.12em; }.quote-sheet-header h2 { margin:0; color:var(--issuer-color); font-size:38px; letter-spacing:.02em; }.quote-sheet-header-note { display:flex; align-items:baseline; gap:9px; color:#256075; font-size:17px; }.quote-sheet-header-note strong { color:var(--issuer-accent); font-size:36px; }.quote-card-grid { display:grid; grid-template-columns:repeat(4, 1fr); gap:17px; padding-top:26px; }.quote-card { overflow:hidden; border:1px solid #b9d8df; border-radius:10px; background:#fff; box-shadow:0 3px 9px #0a67801f; }.quote-card-header { display:flex; align-items:center; justify-content:space-between; gap:8px; min-height:66px; padding:13px 15px; color:#fff; background:linear-gradient(125deg,var(--issuer-color),var(--issuer-accent)); }.quote-card-header strong { display:block; font-size:24px; }.quote-card-header small { font-size:15px; opacity:.92; }.quote-card-number { display:inline-block; margin-right:5px; font-size:14px; font-weight:bold; opacity:.8; }.quote-card-issuer { max-width:96px; text-align:right; font-size:15px; font-weight:bold; letter-spacing:.03em; }.quote-card-summary { display:grid; grid-template-columns:1fr 1fr; background:var(--issuer-soft); }.quote-card-summary div { padding:13px 15px; }.quote-card-summary div + div { border-left:1px solid #b9d8df; }.quote-card-summary span, .quote-detail > span { display:block; color:#286174; font-size:15px; }.quote-card-summary strong { display:block; margin-top:4px; font-size:24px; }.quote-highlight { color:var(--issuer-color); }.quote-card-details { display:grid; grid-template-columns:1fr 1fr; }.quote-detail { min-height:76px; padding:13px 15px; border-top:1px solid #d4e7e9; }.quote-detail:nth-child(odd) { border-right:1px solid #d4e7e9; }.quote-detail strong{ display:inline-block; margin-top:5px; font-size:var(--text-title3); }.quote-detail em{ display:block; margin-top:3px; color:var(--issuer-color); font-size:var(--text-subheadline); font-style:normal; }.quote-detail.underlyings { grid-column:1 / -1; min-height:102px; }.quote-detail ul { display:flex; flex-wrap:wrap; gap:7px 10px; padding:0; margin:8px 0 0; list-style:none; }.quote-detail li{ padding:5px 9px; border-radius:4px; background:#e4f2f4; color:#155066; font-size:var(--text-headline); font-weight:bold; }.quote-dac-note{ margin:5px 0 0; color:#1b7180; font-size:var(--text-footnote); line-height:1.35; }.quote-card-footer { display:flex; flex-wrap:wrap; justify-content:space-between; gap:8px; padding:11px 15px; background:#eaf4f6; color:#236074; font-size:13px; }.quote-card-maker { flex:1 0 100%; padding-top:7px; border-top:1px solid #c8dfe4; text-align:left; font-weight:bold; }.quote-sheet-disclaimer { margin-top:24px; color:#286174; font-size:13px; text-align:right; }
.guide-shell { max-width:1040px; margin:0 auto; padding:32px 24px 48px; }.guide-shell h1 { color:#073b5c; margin:20px 0 8px; }.guide-intro { color:#52616b; }.back-link { color:#075c8a; font-weight:bold; }.guide-section { margin-top:24px; padding:22px; background:#fff; border:1px solid #d5e1e7; border-radius:12px; line-height:1.6; }.guide-section h2 { margin-top:0; color:#0b4a6f; }.guide-table-scroll { overflow:auto; }.guide-table { min-width:650px; width:100%; border-collapse:collapse; }.guide-table th { position:static; background:#0b4a6f; color:#fff; }.guide-table td, .guide-table th { border:1px solid #d5e1e7; padding:10px; text-align:left; vertical-align:top; }.guide-table td:first-child { position:static; min-width:190px; background:#eef5f8; text-align:left; }
@media (min-width: 761px) {
  .app-shell { max-width:1920px; padding:20px; }
  .entry-workspace { padding:14px; }
  .table-card { overflow:hidden; border:1px solid #b9d4da; border-radius:12px; background:#fff; box-shadow:0 7px 18px #0b536018; }
  .table-scroll { overflow-x:auto; overflow-y:visible; scrollbar-gutter:stable; overscroll-behavior-inline:contain; }
  #quoteTable { display:table; width:100%; min-width:1480px; table-layout:fixed; border-collapse:separate; border-spacing:0; }
  #quoteTable thead { display:table-header-group; }
  #quoteTable tbody { display:table-row-group; }
  #quoteTable tr { position:static; display:table-row; padding:0; border:0; border-radius:0; background:#fff; box-shadow:none; }
  #quoteTable th,
  #quoteTable td { display:table-cell; min-width:0; padding:5px 4px; border:0; border-right:1px solid #d8e6e8; border-bottom:1px solid #d8e6e8; vertical-align:middle; }
  #quoteTable th{ position:sticky; top:0; z-index:3; height:54px; padding:7px 5px; background:#1b7fa8; color:#fff; font-size:var(--text-caption); font-weight:600; line-height:1.15; text-align:center; white-space:normal; }
  #quoteTable th:nth-child(n+6):nth-child(-n+10) { background:#0f8163; }
  #quoteTable th:nth-child(n+11):nth-child(-n+16) { background:#0a7c8a; }
  #quoteTable th:nth-child(n+17) { background:#2a6f78; }
  #quoteTable th:first-child { left:0; z-index:4; background:#06626e; }
  #quoteTable tbody tr:last-child td { border-bottom:0; }
  @media (hover:hover) and (pointer:fine){#quoteTable tbody tr:hover td:not(.row-number){ background:#eff9f8; }}
  #quoteTable td.group-basic { background:#1b7fa80a; }
  #quoteTable td.group-underlying { background:#128a6a0d; }
  #quoteTable td.group-payoff { background:#0a7c8a0a; }
  #quoteTable td.group-risk { background:#2a6f780a; }
  #quoteTable .row-number{ position:sticky; left:0; z-index:2; display:table-cell; width:38px; min-width:38px; height:auto; padding:5px 3px; border-radius:0; background:var(--accent); color:#fff; font-size:var(--text-caption); text-align:center; vertical-align:middle; }
  #quoteTable .quote-field,
  #quoteTable .quote-field[data-field] { grid-column:auto; }
  #quoteTable .field-label,
  #quoteTable .group-underlying .field-label,
  #quoteTable .group-payoff .field-label,
  #quoteTable .group-risk .field-label { display:block; min-height:0; padding:0; border:0; border-radius:0; background:transparent; box-shadow:none; }
  #quoteTable .field-label-text { display:none; }
  /* 11px was below comfortable reading size for an all-day data-entry screen. The table already
     scrolls horizontally, so the extra width this costs is cheaper than the misreads it prevents. */
  #quoteTable input,
  #quoteTable select{ min-height:38px; padding:5px 6px; border-color:var(--separator-solid); border-radius:7px; font-size:var(--text-footnote); line-height:1.2; }
  #quoteTable input[type="number"] { appearance:textfield; }
  #quoteTable input[type="number"]::-webkit-inner-spin-button,
  #quoteTable input[type="number"]::-webkit-outer-spin-button { margin:0; appearance:none; }
  #quoteTable th:nth-child(1) { width:34px; }
  #quoteTable th:nth-child(2) { width:52px; }
  #quoteTable th:nth-child(3) { width:54px; }
  #quoteTable th:nth-child(4) { width:78px; }
  #quoteTable th:nth-child(5) { width:44px; }
  #quoteTable th:nth-child(n+6):nth-child(-n+10) { width:68px; }
  #quoteTable th:nth-child(11) { width:54px; }
  #quoteTable th:nth-child(12) { width:82px; }
  #quoteTable th:nth-child(13),
  #quoteTable th:nth-child(14),
  #quoteTable th:nth-child(18),
  #quoteTable th:nth-child(19) { width:58px; }
  #quoteTable th:nth-child(15) { width:66px; }
  #quoteTable th:nth-child(16) { width:64px; }
  #quoteTable th:nth-child(17) { width:60px; }
  #quoteTable th:nth-child(20) { width:50px; }
  #quoteTable th:nth-child(21) { width:74px; }
}

/* Cloudflare 後端模式：只在 app.yintsun66.com 由 backend-client.js 顯示。 */
/* Breakpoints — five, and each one earns its place.

   Add rules to an existing breakpoint rather than introducing a sixth. Plain CSS cannot read a
   custom property inside a media query, so these cannot be tokens; this comment is the only
   place the set is written down.

     460px  very small phones — page chrome only (app shell, hero, toolbar, legend)
     600px  backend dialog internals get cramped (panels, lists, rankings, artifact viewer)
     700px  backend cards and metrics reflow (timeline, health grid, RFQ history)
     760px  THE structural one: the 21-column table becomes stacked cards, fixed-value fields
            hide, and the trade navigator appears. Paired with min-width: 761px, which carries
            the table layout. ADR and CLAUDE.md both depend on this number — do not move it.
     900px  entry-workspace header and legend stack. Paired with min-width: 901px.

   600 and 700 look mergeable and are not: both are backend-only, but merging them would push
   21 dialog rules 100px wider and change how dialogs look on a tablet. They stay separate until
   someone has a reason and a screenshot. */

.backend-shell{position:relative;z-index:1000}.backend-userbar{position:fixed;right:18px;bottom:18px;display:flex;align-items:center;gap:12px;padding:10px 14px;border:1px solid #80cabb;border-radius:14px;background:#f2fbf9;box-shadow:0 10px 28px rgba(8,55,72,.16);color:#0b4a6f;font-weight:700}.backend-dialog{border:0;border-radius:20px;padding:0;box-shadow:0 24px 70px rgba(4,41,60,.3);max-width:min(94vw,520px)}.backend-dialog::backdrop{background:rgba(3,34,49,.68);backdrop-filter:blur(4px)}.backend-panel{padding:30px;background:linear-gradient(145deg,#fff,#effaf8);min-width:min(440px,88vw)}.backend-panel label{display:grid;gap:6px;margin:14px 0;color:#174d62;font-weight:700}.backend-panel input{width:100%;padding:12px;border:1px solid #91c7c3;border-radius:9px;font:inherit}.backend-error{min-height:1.4em;color:#a12d39}.backend-results-dialog{max-width:min(96vw,1100px);width:1100px}.backend-results-dialog .backend-panel{min-width:0}.backend-results-heading{display:flex;justify-content:space-between;gap:20px;align-items:start}.backend-countdown{font-size:var(--text-headline);font-weight:800;color:#075f73}.backend-finalize-confirm{display:grid;gap:10px;margin:14px 0;padding:16px 18px;border:2px solid #168a77;border-left-width:7px;border-radius:13px;background:linear-gradient(135deg,#e5f8f2,#edf6fb);box-shadow:0 7px 18px rgba(10,74,96,.12);color:#174d62}.backend-finalize-confirm[hidden]{display:none}.backend-finalize-confirm strong{color:#075f73;font-size:var(--text-headline)}.backend-finalize-confirm p{margin:0;line-height:1.6}.backend-finalize-confirm .dialog-actions{display:flex;justify-content:flex-end;gap:9px;margin-top:2px}.backend-issuer-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(120px,1fr));gap:8px}.issuer-state{display:grid;gap:3px;padding:10px;border:1px solid #afd7d3;border-radius:10px;background:#fff;font-size:var(--text-caption);color:#477}.issuer-state b{font-size:var(--text-subheadline);color:#0b4a6f}.status-valid_reply{border-color:#42ad85;background:#ebfaf4}.status-timeout,.status-parse_error{border-color:#d8a073;background:#fff6ed}.backend-rankings{display:grid;gap:16px;margin-top:20px}.ranking-card{padding:16px;border:1px solid #a9d7d2;border-radius:14px;background:#fff}.ranking-card h3{margin:0 0 12px;color:#0b4a6f}.ranking-card small{margin-left:8px;color:#168a77}.ranking-card table{width:100%;border-collapse:collapse}.ranking-card th,.ranking-card td{padding:9px;border-bottom:1px solid #d5e8e8;text-align:left}.ranking-card th{background:#0b5c73;color:#fff}.backend-artifacts{display:flex;flex-wrap:wrap;gap:10px;margin-top:20px}.artifact-link{text-decoration:none}.artifact-pending{padding:10px;border-radius:8px;background:#e9f4f5;color:#315c68}@media (max-width: 600px){.backend-results-heading{display:block}.backend-dialog{max-width:96vw}.backend-panel{padding:20px}.backend-finalize-confirm .dialog-actions{display:grid;grid-template-columns:1fr}.backend-finalize-confirm .dialog-actions button{width:100%}.ranking-card{overflow-x:auto}.backend-userbar{left:12px;right:12px;justify-content:space-between}}
.backend-password-warning{margin:12px 0;padding:12px 14px;border-left:5px solid #168a77;border-radius:10px;background:#e4f6f2;color:#174d62;line-height:1.55;font-weight:700}
@media (max-width: 900px) { .entry-workspace-header { align-items:flex-start; flex-direction:column; }.field-group-legend { justify-content:flex-start; } }
@media (max-width: 760px) { .app-shell,.guide-shell { padding:14px; }.hero { padding:24px; align-items:flex-start; flex-direction:column; border-radius:16px; }.quote-count { padding:10px 14px; }.toolbar { display:grid; grid-template-columns:1fr 1fr; }.toolbar button,.toolbar .guide-link { width:100%; }.toolbar #sendQuotes,.toolbar #generateQuoteImage,.toolbar .guide-link { grid-column:span 2; }.entry-workspace { padding:14px; border-radius:14px; }.entry-workspace-header { margin-bottom:14px; }.field-group-legend span{ padding:5px 8px; font-size:var(--text-caption2); } #quoteTable tr { grid-template-columns:repeat(2,minmax(0,1fr)); gap:9px; padding:47px 12px 12px; border-radius:12px; } #quoteTable .quote-field,#quoteTable .quote-field[data-field] { grid-column:span 1; } #quoteTable .quote-field[data-field="bbgCode1"],#quoteTable .quote-field[data-field="tradeDate"],#quoteTable .quote-field[data-field="koType"] { grid-column:span 2; } #quoteTable .field-label { min-height:76px; padding:9px; } #quoteTable input,#quoteTable select{ min-height:44px; font-size:var(--text-callout); }.guide-section { padding:16px; }.quote-preview-panel { padding:12px; }.preview-heading { align-items:flex-start; flex-direction:column; }.quote-sheet { transform-origin:top left; }.dialog-actions { flex-direction:column-reverse; }.dialog-actions button { width:100%; } }
@media (max-width: 760px) {
  .trade-navigator { position:sticky; top:8px; z-index:8; display:block; margin:0 0 14px; padding:10px 11px 9px; border:1px solid #9fd4cc; border-radius:13px; background:linear-gradient(135deg,#f8fffff2,#e9f8f5f2); box-shadow:0 8px 22px #07556824; backdrop-filter:blur(10px); }
  .trade-navigator-heading{ display:flex; align-items:center; justify-content:space-between; gap:12px; margin-bottom:8px; color:#0b536c; font-size:var(--text-footnote); }
  .trade-navigator-heading span { color:#087763; font-weight:800; }
  .trade-shortcuts { display:flex; gap:8px; overflow-x:auto; padding:1px 1px 7px; scroll-snap-type:x proximity; scrollbar-width:thin; scrollbar-color:#83c9bd transparent; -webkit-overflow-scrolling:touch; }
  .trade-shortcut { flex:0 0 46px; min-height:42px; scroll-snap-align:center; border:1px solid #9ac9ce; border-radius:999px; background:#fff; color:#145c71; font-weight:900; cursor:pointer; }
  .trade-shortcut.is-active { border-color:#087766; background:linear-gradient(135deg,#086b8a,#0b7a5f); color:#fff; box-shadow:0 4px 10px #07697d38; }
  .trade-shortcut:focus-visible { outline:3px solid #79daca; outline-offset:2px; }
  .trade-navigator p{ margin:1px 2px 0; color:#4b6e76; font-size:var(--text-caption); line-height:1.35; }
  #quoteTable tr { scroll-margin-top:132px; transition:border-color .18s ease,box-shadow .18s ease; }
  #quoteTable tr.active-trade { border-color:#61bfb1; box-shadow:0 7px 18px #08796824; }
  #quoteTable .quote-field[data-field="observationFrequency"],
  #quoteTable .quote-field[data-field="otc"],
  #quoteTable .quote-field[data-field="effectiveDateOffset"] { display:none; }
}
@media (max-width: 460px) { .app-shell,.guide-shell { padding:10px; }.hero { padding:20px; }.toolbar { grid-template-columns:1fr; }.toolbar #sendQuotes,.toolbar #generateQuoteImage,.toolbar .guide-link { grid-column:span 1; }.entry-workspace { padding:10px; }.field-group-legend { gap:5px; } #quoteTable tr { grid-template-columns:1fr; padding:45px 10px 10px; } #quoteTable .quote-field,#quoteTable .quote-field[data-field],#quoteTable .quote-field[data-field="bbgCode1"],#quoteTable .quote-field[data-field="tradeDate"],#quoteTable .quote-field[data-field="koType"] { grid-column:span 1; } }
.backend-archive-dialog{width:min(1180px,96vw);max-width:1180px}.backend-archive-note{color:#315c68;line-height:1.5}.backend-archive-list{max-height:280px;overflow:auto;border:1px solid #c7dddd;border-radius:10px;background:#fff}.backend-archive-list table{width:100%;border-collapse:collapse;font-size:var(--text-subheadline)}.backend-archive-list th,.backend-archive-list td{padding:9px;border-bottom:1px solid #d9e9e8;text-align:left;vertical-align:top}.backend-archive-list th{position:sticky;top:0;background:#0b5c73;color:#fff}.backend-archive-list small{display:block;margin-top:3px;color:#58747b}.backend-archive-empty{padding:16px;margin:0;color:#58747b}.backend-archive-preview{margin-top:18px;padding:16px;border:1px solid #a9d7d2;border-radius:14px;background:#fff}.backend-archive-preview h3{margin:0;color:#0b4a6f;word-break:break-word}.backend-archive-preview p{margin:8px 0 12px;color:#58747b;font-size:var(--text-subheadline)}.backend-archive-preview iframe{display:block;width:100%;min-height:420px;border:1px solid #c7dddd;border-radius:8px;background:#fff}
.backend-registration-dialog{width:min(1050px,96vw);max-width:1050px}.backend-registration-list{max-height:420px;overflow:auto;border:1px solid #c7dddd;border-radius:10px;background:#fff}.backend-registration-list table{width:100%;border-collapse:collapse;font-size:var(--text-subheadline)}.backend-registration-list th,.backend-registration-list td{padding:10px;border-bottom:1px solid #d9e9e8;text-align:left;vertical-align:middle}.backend-registration-list th{position:sticky;top:0;background:#0b5c73;color:#fff}.backend-registration-actions{display:flex;gap:7px;min-width:132px}.backend-registration-actions button{min-height:34px;padding:5px 10px}.backend-admin-status{min-height:1.4em;margin:0 0 10px;color:#08745c;font-weight:700}@media (max-width: 600px){.backend-registration-list{max-height:360px}.backend-registration-list table{min-width:760px}.backend-registration-actions{min-width:126px}}
.backend-card-preview{width:min(560px,96vw);max-width:560px}.backend-card-preview .backend-panel{min-width:0}.backend-card-preview-frame{max-height:62vh;overflow:auto;margin:12px 0;padding:10px;border:1px solid #c8e0e2;border-radius:10px;background:#eaf4f6;text-align:center}.backend-card-preview-frame img{display:block;width:100%;height:auto;border-radius:6px;box-shadow:0 5px 16px rgba(10,55,75,.16)}.backend-card-preview .artifact-link{display:inline-flex;align-items:center;justify-content:center;min-height:44px;padding:10px 18px;border-radius:8px;background:#0b5c73;color:#fff;font-weight:800;text-decoration:none}
.backend-card-preview{position:fixed;inset:0;z-index:100;width:auto;max-width:none;display:grid;place-items:center;padding:16px;background:rgba(3,34,49,.72)}.backend-card-preview>.backend-panel{width:min(560px,100%);max-height:calc(100dvh - 32px);overflow:auto;border-radius:18px;box-shadow:0 24px 70px rgba(4,41,60,.34)}.backend-card-preview-frame{max-height:62dvh}.backend-card-preview-frame img{width:min(100%,720px);margin:auto}.backend-card-preview-actions{display:flex;flex-wrap:wrap;gap:10px}.backend-card-open-link{display:none!important}@media (min-width: 901px) and (hover:hover) and (pointer:fine){.backend-card-open-link{display:inline-flex!important}}
.backend-dup-note{margin:0 0 12px;padding:10px 12px;border:1px solid #e0b64a;border-radius:9px;background:#fdf6e3;color:#8a5a00;font-weight:700;line-height:1.5}.backend-dup-note[hidden]{display:none}
.backend-account-lookup{display:flex;flex-wrap:wrap;align-items:center;gap:8px;margin:0 0 12px;padding:10px 12px;border:1px solid #a9d7d2;border-radius:10px;background:#f2fbf9}.backend-account-lookup[hidden]{display:none}.backend-account-lookup label{color:#0b4a6f;font-weight:800}.backend-account-lookup input{width:120px;padding:8px 10px;border:1px solid #91c7c3;border-radius:8px;font:inherit}.backend-account-lookup button{min-height:36px;padding:6px 14px}.backend-account-lookup-result{color:#0b4a6f;font-weight:700}
.backend-accounts-dialog{width:min(1080px,96vw);max-width:1080px}.backend-accounts-list{max-height:70vh;overflow:auto;border:1px solid #c7dddd;border-radius:10px;background:#fff}.backend-accounts-list table{width:100%;border-collapse:collapse;font-size:var(--text-subheadline)}.backend-accounts-list th,.backend-accounts-list td{padding:10px;border-bottom:1px solid #d9e9e8;text-align:left;vertical-align:middle}.backend-accounts-list th{position:sticky;top:0;background:#0b5c73;color:#fff}.backend-accounts-list small{color:#58747b}.backend-accounts-list .backend-registration-actions{flex-wrap:wrap;min-width:150px}@media (max-width: 600px){.backend-accounts-list table{min-width:820px}}
.backend-accounts-list .backend-lifecycle-table{min-width:2850px}.backend-lifecycle-table td,.backend-lifecycle-table th{white-space:nowrap}
.backend-lifecycle-filters{display:grid;grid-template-columns:repeat(4,minmax(150px,1fr));gap:10px;margin:15px 0;padding:14px;border:1px solid #b8d9d5;border-radius:13px;background:#f5fbfa}.backend-lifecycle-filters label{display:grid;gap:5px;margin:0;color:#315c68;font-size:var(--text-footnote);font-weight:800}.backend-lifecycle-filters input,.backend-lifecycle-filters select{width:100%;min-height:42px;padding:8px 10px;border:1px solid #87c3ba;border-radius:8px;background:#fff;color:#164b5e;font:inherit}.backend-lifecycle-filter-actions{display:flex;align-items:end;gap:8px}.backend-lifecycle-filter-actions button{min-height:42px;padding:8px 12px}.backend-lifecycle-table tr.backend-lifecycle-expired>td{background:#fff2e4;color:#72401f}.backend-lifecycle-table tr.backend-lifecycle-expired-maturity>td{background:#eef1f5;color:#475462}@media (hover:hover) and (pointer:fine){.backend-lifecycle-table tr.backend-lifecycle-expired:hover>td{background:#ffe5cc}}@media (hover:hover) and (pointer:fine){.backend-lifecycle-table tr.backend-lifecycle-expired-maturity:hover>td{background:#e2e8ee}}.backend-lifecycle-status{display:inline-flex;padding:4px 9px;border-radius:999px;font-weight:900}.backend-lifecycle-status-current{background:#e1f5ef;color:#08745c}.backend-lifecycle-status-expire{background:#f4d7c1;color:#8c3d1a}@media (max-width:760px){.backend-lifecycle-filters{grid-template-columns:repeat(2,minmax(0,1fr));padding:11px}.backend-lifecycle-filter-actions{grid-column:1/-1}.backend-lifecycle-filter-actions button{flex:1}}@media (max-width:460px){.backend-lifecycle-filters{grid-template-columns:1fr}.backend-lifecycle-filter-actions{grid-column:auto}}
.backend-timeline-dialog{width:min(1120px,96vw);max-width:1120px}.backend-timeline-list{display:grid;gap:12px;max-height:70vh;overflow:auto}.backend-timeline-card{padding:15px;border:1px solid #a9d7d2;border-radius:14px;background:#fff}.backend-timeline-card header{display:flex;justify-content:space-between;gap:12px;color:#0b4a6f}.backend-timeline-card header div{display:grid}.backend-timeline-card header small,.backend-timeline-card>small{color:#58747b}.backend-timeline-card header>span{padding:5px 9px;border-radius:999px;background:#e4f6f2;color:#08745c;font-weight:800}.backend-timeline-metrics{display:grid;grid-template-columns:repeat(4,minmax(150px,1fr));gap:7px;margin:12px 0}.backend-timeline-metrics span{padding:8px;border-radius:8px;background:#edf7f7;color:#315c68}.backend-timeline-issuers{display:grid;grid-template-columns:repeat(auto-fit,minmax(105px,1fr));gap:6px;margin:10px 0}@media (max-width: 700px){.backend-timeline-metrics{grid-template-columns:1fr 1fr}}
.backend-rfq-health{margin:12px 0}.backend-health-panel{padding:14px;border:1px solid #8bcfc5;border-radius:15px;background:linear-gradient(135deg,#eef9fb,#edf9f3)}.backend-health-panel>header{display:flex;justify-content:space-between;gap:12px;align-items:end;margin-bottom:10px}.backend-health-panel h3{margin:0;color:#0b4a6f}.backend-health-panel header small{color:#58747b}.backend-health-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(145px,1fr));gap:8px}.backend-health-grid article{display:grid;gap:3px;padding:10px;border:1px solid #c2e3df;border-radius:10px;background:#fff}.backend-health-grid article>b{color:#0b4a6f}.backend-health-grid strong{font-size:var(--text-title3);color:#078363}.backend-health-grid small{color:#58747b;line-height:1.45}.backend-health-alerts{display:flex;flex-wrap:wrap;gap:7px;margin-top:10px}.backend-health-alerts span{padding:6px 9px;border-radius:999px;background:#fff0e5;color:#9a4f12;font-size:var(--text-subheadline)}.backend-health-alerts b{margin-right:4px}.backend-health-ok{margin:10px 0 0;color:#08745c;font-weight:700}@media (max-width: 700px){.backend-health-panel>header{display:grid}.backend-health-grid{grid-template-columns:1fr}}
.backend-provisional{padding:12px 14px;border:1px solid #49a998;border-radius:10px;background:#eaf9f5;color:#075f73;font-weight:800}.issuer-picker-summary{margin:12px 0 4px;padding:10px 12px;border:1px solid #87cfc0;border-radius:10px;background:#eaf9f5;color:#075f73;font-weight:800}.artifact-request{margin-left:8px;min-height:32px;padding:4px 9px}.attention{border-color:#078d70!important;background:#dff8ef!important;color:#075f73!important;box-shadow:0 0 0 3px rgba(7,141,112,.16)}
.custom-fifth-row{background:#eefaf7}.custom-fifth-row td:first-child{font-weight:800;color:#087966}.custom-fifth-row select{width:100%;min-width:150px;padding:7px 9px;border:1px solid #55aa9c;border-radius:8px;background:#fff;color:#164b5e;font:inherit;font-weight:700}.admin-rfq-recalculate{margin-top:10px}
.backend-userbar{flex-wrap:wrap}
.backend-artifacts{display:block;margin-top:22px}.backend-artifact-viewer{padding:18px;border:1px solid #9fcfca;border-radius:16px;background:linear-gradient(145deg,#f4fbfb,#edf8f5)}.backend-artifact-toolbar{display:grid;grid-template-columns:auto minmax(220px,360px);align-items:center;gap:8px 14px;margin-bottom:18px}.backend-artifact-toolbar label{color:#0b4a6f;font-weight:800}.backend-artifact-toolbar select{min-height:44px;padding:8px 12px;border:1px solid #72bcb4;border-radius:9px;background:#fff;color:#173f51;font:inherit;font-weight:700}.backend-artifact-toolbar p{grid-column:1/-1;margin:0;color:#426776;font-size:var(--text-subheadline)}.backend-artifact-preview-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(280px,1fr));gap:18px}.backend-artifact-preview-card{display:grid;justify-items:center;gap:13px;margin:0;padding:16px;border:1px solid #b9d8df;border-radius:14px;background:#fff;box-shadow:0 7px 20px rgba(10,74,96,.12)}.backend-artifact-preview-card h3{justify-self:start;margin:0;color:#0b4a6f}.backend-artifact-preview-frame{display:flex;justify-content:center;width:100%;max-height:680px;overflow:auto;padding:10px;border:1px solid #c8e0e2;border-radius:10px;background:#eaf4f6}.backend-artifact-preview-frame img{display:block;width:min(100%,430px);height:auto;border-radius:6px;box-shadow:0 5px 16px rgba(10,55,75,.16)}.backend-artifact-preview-card .artifact-link{display:inline-flex;align-items:center;justify-content:center;min-height:42px;padding:9px 15px;border-radius:8px}.backend-artifact-viewer>.artifact-pending{margin:0}@media (max-width: 600px){.backend-artifact-viewer{padding:12px}.backend-artifact-toolbar{grid-template-columns:1fr}.backend-artifact-toolbar p{grid-column:1}.backend-artifact-preview-grid{grid-template-columns:1fr}.backend-artifact-preview-frame{max-height:72vh;padding:6px}.backend-artifact-preview-frame img{width:100%}}
.backend-rfq-badge{display:inline-grid;place-items:center;min-width:22px;height:22px;margin-left:4px;padding:0 6px;border-radius:999px;background:#067a60;color:#fff;font-size:var(--text-caption);font-weight:900}.backend-rfq-history-dialog{width:min(960px,96vw);max-width:960px}.backend-rfq-tabs{display:flex;gap:8px;margin:18px 0 12px}.backend-rfq-tabs button[aria-selected="true"]{border-color:#078d70;background:#dff8ef;color:#075f73;box-shadow:inset 0 0 0 1px #078d70}.backend-rfq-history-list{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:14px;max-height:65vh;overflow:auto;padding:2px}.backend-rfq-card{display:grid;gap:11px;padding:17px;border:1px solid #afd7d3;border-left:5px solid #168a77;border-radius:14px;background:#fff;box-shadow:0 7px 18px rgba(10,74,96,.1)}.backend-rfq-card.status-completed{border-left-color:#078d70}.backend-rfq-card.status-no_valid_quote,.backend-rfq-card.status-failed,.backend-rfq-card.status-cancelled{border-left-color:#a85e58}.backend-rfq-card header,.backend-rfq-card footer{display:flex;justify-content:space-between;gap:12px;align-items:flex-start}.backend-rfq-card header div{display:grid;min-width:0}.backend-rfq-card header strong{overflow:hidden;color:#0b4a6f;font-size:var(--text-subheadline);text-overflow:ellipsis;white-space:nowrap}.backend-rfq-card header small,.backend-rfq-card>small{color:#58747b}.backend-rfq-card header>span{flex:none;padding:5px 9px;border-radius:999px;background:#e4f6f2;color:#08745c;font-size:var(--text-caption);font-weight:900}.backend-rfq-underlyings{margin:0;color:#173f51;font-size:var(--text-callout);font-weight:800}.backend-rfq-underlyings small{color:#58747b;font-weight:600}.backend-rfq-meta{display:flex;flex-wrap:wrap;gap:6px}.backend-rfq-meta span{padding:5px 8px;border-radius:999px;background:#edf7f7;color:#315c68;font-size:var(--text-caption)}.backend-rfq-progress{height:7px;overflow:hidden;border-radius:999px;background:#dceced}.backend-rfq-progress span{display:block;height:100%;border-radius:inherit;background:linear-gradient(90deg,#078d70,#0a77a8)}.backend-rfq-card footer{align-items:center;margin-top:2px}.backend-rfq-card footer>span{color:#426776;font-size:var(--text-footnote)}.backend-rfq-card footer button{flex:none;min-height:38px;padding:7px 12px}.backend-rfq-card footer .backend-rfq-actions{display:flex;flex-wrap:wrap;gap:8px}.backend-rfq-card footer .backend-rfq-actions button{flex:1 1 auto;width:auto}.backend-rfq-empty{grid-column:1/-1;margin:0;padding:28px;border:1px dashed #9fcfca;border-radius:14px;background:#f7fcfb;color:#426776;text-align:center}.backend-rfq-load-more{display:block;margin:15px auto 0}.backend-rfq-load-more[hidden]{display:none}@media (max-width: 700px){.backend-rfq-history-list{grid-template-columns:1fr;max-height:68vh}.backend-rfq-tabs{display:grid;grid-template-columns:repeat(3,1fr)}.backend-rfq-tabs button{padding:8px 5px}.backend-rfq-card{padding:14px}.backend-userbar #backendUser{width:100%;font-size:var(--text-footnote)}.backend-userbar #backendNewRfq,.backend-userbar #backendMyRfqs{flex:1}.backend-rfq-card footer{align-items:stretch;flex-direction:column}.backend-rfq-card footer button{width:100%}}
.backend-rfq-late{margin:0;padding:9px 11px;border:1px solid #e3b858;border-radius:10px;background:#fff8df;color:#76530b;font-size:var(--text-footnote);font-weight:800}
.issuer-fast-actions{display:flex;flex-wrap:wrap;gap:8px;margin:10px 0 12px;padding:10px;border:1px solid #a9d9d2;border-radius:12px;background:#f2fbf9}.issuer-fast-actions button{min-height:38px;padding:7px 11px}.issuer-fast-actions #issuerFastStart{border-color:#078d70;background:#e4f6f2;color:#075f73;font-weight:800}@media (max-width:700px){.issuer-fast-actions{display:grid;grid-template-columns:1fr}.issuer-fast-actions button{width:100%}}
.backend-mobile-menu-toggle{display:none}.backend-mobile-toggle-icon{display:inline-block;margin-left:4px;transition:transform .18s ease}@media (max-width: 760px){.backend-userbar{left:auto;right:10px;bottom:calc(10px + env(safe-area-inset-bottom,0px));display:flex;flex-wrap:nowrap;justify-content:flex-end;width:auto;max-width:calc(100vw - 20px);padding:6px;gap:6px;border-radius:12px}.backend-userbar #backendMyRfqs{order:0;flex:none;width:auto;min-height:44px;padding:8px 12px}.backend-mobile-menu-toggle{order:1;display:inline-flex;align-items:center;justify-content:center;width:auto;min-width:58px;min-height:44px;padding:8px 10px}.backend-userbar:not(.is-expanded) .backend-mobile-collapsible{display:none!important}.backend-userbar.is-expanded{left:10px;display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);align-items:stretch;max-height:min(70vh,520px);overflow-y:auto;padding:10px;gap:8px}.backend-userbar.is-expanded #backendMyRfqs,.backend-userbar.is-expanded .backend-mobile-menu-toggle{order:-3;width:100%}.backend-userbar.is-expanded #backendUser{order:-2;grid-column:1/-1;width:100%;padding:5px 3px;font-size:var(--text-footnote);text-align:center}.backend-userbar.is-expanded .backend-mobile-collapsible:not(#backendUser){width:100%;min-height:44px}.backend-userbar.is-expanded .backend-mobile-toggle-icon{transform:rotate(180deg)}}

/* 獨立的 FCN／DAC 市場與風險分析頁。現價只存在瀏覽器 localStorage。 */
.analysis-link{display:inline-block;margin-left:8px;color:#087966;font-size:var(--text-footnote);font-weight:800;text-decoration:underline;text-underline-offset:3px}.backend-analysis-view{position:fixed;inset:0;z-index:1100;overflow:auto;padding:24px;background:linear-gradient(155deg,#eaf7f4 0,#f4f9fb 45%,#e8f3f8 100%)}.backend-analysis-view[hidden]{display:none}.backend-analysis-shell{width:min(1180px,100%);margin:0 auto;padding:28px;border:1px solid #acd4d1;border-radius:24px;background:rgba(255,255,255,.94);box-shadow:0 22px 60px rgba(6,57,76,.18)}.backend-analysis-header,.backend-analysis-section-heading{display:flex;align-items:flex-start;justify-content:space-between;gap:20px}.backend-analysis-header h1{margin:2px 0 0;color:#0a4f70;font-size:clamp(2rem,4vw,3.2rem)}.backend-analysis-back{display:inline-flex;align-items:center;justify-content:center;min-height:44px;padding:9px 15px;text-decoration:none}.backend-analysis-lead{margin:12px 0 22px;color:#416b78;font-size:var(--text-headline)}.backend-analysis-loading{padding:42px;border:1px dashed #85bdb5;border-radius:16px;color:#315c68;text-align:center}.backend-analysis-hero{display:flex;align-items:end;justify-content:space-between;gap:24px;padding:26px;border-radius:18px;background:linear-gradient(125deg,#087e68,#0a6f9a);color:#fff}.backend-analysis-hero span{font-weight:800;letter-spacing:.04em}.backend-analysis-hero h2{margin:9px 0 4px;font-size:var(--text-largetitle)}.backend-analysis-hero p{margin:0;font-size:var(--text-headline)}.backend-analysis-hero label{display:grid;gap:7px;min-width:min(360px,100%);font-weight:800}.backend-analysis-hero select{min-height:46px;padding:9px 12px;border:1px solid #a8dcd5;border-radius:9px;background:#fff;color:#164b5e;font:inherit;font-weight:700}.backend-analysis-section{margin-top:20px;padding:22px;border:1px solid #b8d9d6;border-radius:17px;background:#fff}.backend-analysis-section h2,.backend-analysis-paths h2{margin:3px 0 15px;color:#0b5570}.backend-analysis-terms{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:10px}.backend-analysis-terms>span{display:grid;gap:5px;padding:13px;border-radius:11px;background:#eef8f6;color:#3c6974}.backend-analysis-terms b{color:#123e52;font-size:var(--text-title3)}.backend-analysis-terms small{color:#07815f;font-weight:800}.backend-analysis-note{color:#416b78;line-height:1.6}.backend-analysis-spots{display:grid;grid-template-columns:repeat(auto-fit,minmax(210px,1fr));gap:12px}.backend-analysis-spot-card{padding:15px;border:1px solid #b7d9d5;border-radius:13px;background:#f4fbf9}.backend-analysis-spot-card h3{margin:0 0 12px;color:#0b4f6a}.backend-analysis-spot-card label{display:grid;gap:5px;margin-top:9px;color:#315c68;font-weight:700}.backend-analysis-spot-card input{width:100%;min-height:42px;padding:8px 10px;border:1px solid #87c3ba;border-radius:8px;background:#fff;font:inherit}.backend-analysis-spot-card small{display:block;margin-top:10px;color:#607a82;line-height:1.45}.backend-analysis-metrics{display:flex;flex-wrap:wrap;justify-content:flex-end;gap:8px}.backend-analysis-metrics span{padding:9px 12px;border-radius:999px;background:#e4f6f1;color:#315c68}.backend-analysis-metrics b{color:#087966}.backend-analysis-table-wrap{overflow:auto;border:1px solid #c7e0df;border-radius:11px}.backend-analysis-table-wrap table{width:100%;border-collapse:collapse;min-width:720px}.backend-analysis-table-wrap th,.backend-analysis-table-wrap td{padding:11px 12px;border-bottom:1px solid #dbeae9;text-align:left;vertical-align:top;line-height:1.45}.backend-analysis-table-wrap th{background:#0b5c73;color:#fff;white-space:nowrap}.backend-analysis-table-wrap tbody tr:nth-child(even){background:#f4faf9}.backend-analysis-paths{margin-top:20px;padding:22px;border:1px solid #b8d9d6;border-radius:17px;background:#f1faf7}.backend-analysis-paths>div{display:grid;grid-template-columns:1fr 1fr;gap:12px}.backend-analysis-paths article{padding:16px;border-left:5px solid #0a8068;border-radius:10px;background:#fff}.backend-analysis-paths h3{margin:0;color:#0b5570}.backend-analysis-paths p{margin:8px 0 0;color:#416b78;line-height:1.6}.backend-analysis-disclaimer{margin:20px 0 0;padding:15px 17px;border-radius:12px;background:#fff5df;color:#76510d;font-weight:700;line-height:1.65}
.backend-analysis-underlyings-term{grid-column:span 2}.backend-analysis-underlyings-term b{overflow-wrap:anywhere}.backend-analysis-product-warning{margin-top:20px;padding:18px 20px;border:2px solid #0b8e72;border-left-width:7px;border-radius:14px;background:linear-gradient(135deg,#e0f8ef,#e7f3fb);box-shadow:0 8px 22px rgba(7,94,112,.12);color:#164b5e}.backend-analysis-product-warning strong{display:block;color:#08745c;font-size:var(--text-headline)}.backend-analysis-product-warning p{margin:8px 0 0;font-weight:800;line-height:1.65}
.backend-market-resources{margin-top:20px;border:1px solid #96c9c2;border-radius:17px;background:#f5fbfa}.backend-market-resources>summary{cursor:pointer;padding:18px 22px;color:#0b5570;font-size:var(--text-headline);font-weight:900}.backend-market-resources[open]>summary{border-bottom:1px solid #c7e0dc}.backend-market-resources-body{padding:20px 22px}.backend-market-consent{padding:14px;border:1px solid #b7d9d5;border-radius:12px;background:#fff;color:#315c68;line-height:1.55}.backend-market-consent label{display:flex;align-items:flex-start;gap:9px}.backend-market-consent input{flex:none;margin-top:4px}.backend-market-controls{display:flex;align-items:end;flex-wrap:wrap;gap:10px;margin-top:14px}.backend-market-controls label{display:grid;gap:5px;min-width:min(320px,100%);color:#315c68;font-weight:800}.backend-market-controls select{min-height:44px;padding:8px 10px;border:1px solid #87c3ba;border-radius:8px;background:#fff;color:#164b5e;font:inherit}.backend-market-status{min-height:1.4em;color:#416b78;font-weight:700}.backend-market-widget{overflow:hidden;width:100%;border-radius:13px;background:#edf6f5}.backend-market-widget iframe{display:block;width:100%;height:520px;border:1px solid #b7d9d5;border-radius:13px;background:#fff}.backend-market-links{display:grid;grid-template-columns:repeat(auto-fit,minmax(230px,1fr));gap:10px;margin-top:15px}.backend-market-links article{padding:14px;border:1px solid #c5dfdc;border-radius:12px;background:#fff}.backend-market-links h3{margin:0 0 9px;color:#0b5570}.backend-market-links h3 small{color:#607a82;font-size:var(--text-caption)}.backend-market-links p{color:#58747b;line-height:1.45}.backend-market-links nav{display:flex;flex-wrap:wrap;gap:7px}.backend-market-links a{display:inline-flex;padding:6px 9px;border-radius:999px;background:#e4f6f1;color:#08745c;font-size:var(--text-footnote);font-weight:800;text-decoration:none}@media (hover:hover) and (pointer:fine){.backend-market-links a:hover,.backend-market-links a:focus-visible{background:#ccece4}}.backend-market-source-note{margin:15px 0 0;color:#607a82;font-size:var(--text-footnote);line-height:1.55}
.backend-market-context{margin:14px 0}.backend-market-context-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(310px,1fr));gap:12px}.backend-market-context-card{padding:16px;border:1px solid #b7d9d5;border-radius:14px;background:#fff;color:#315c68}.backend-market-context-card>header{display:flex;justify-content:space-between;gap:12px;align-items:flex-start}.backend-market-context-card h3,.backend-market-context-card h4{margin:0;color:#0b5570}.backend-market-context-card header>span,.backend-market-ideas-section>header>span{padding:5px 8px;border-radius:999px;background:#e4f6f1;color:#08745c;font-size:var(--text-caption);font-weight:900}.backend-market-context-card dl{display:flex;flex-wrap:wrap;gap:8px;margin:14px 0}.backend-market-context-card dl>div{min-width:100px;padding:8px;border-radius:9px;background:#f0f8f7}.backend-market-context-card dt{font-size:var(--text-caption)}.backend-market-context-card dd{margin:2px 0 0;color:#123f51;font-weight:900}.backend-market-context-card ul{display:grid;gap:7px;padding:0;list-style:none}.backend-market-context-card li{display:grid;grid-template-columns:55px 1fr auto;gap:8px;align-items:center;padding:8px;border-bottom:1px solid #e0eeec}.backend-market-context-card a{color:#08745c;font-weight:800}.backend-alpha-card{background:linear-gradient(145deg,#f4fbfb,#eef9f3)}.backend-market-close{display:block;margin:15px 0 3px;color:#078363;font-size:clamp(1.7rem,4vw,2.45rem)}.backend-apply-close{display:inline;padding:0 0 0 6px;font-size:inherit}.backend-market-ideas{display:grid;gap:14px;margin:14px 0}.backend-market-ideas-section{padding:17px;border:1px solid #9bcfc8;border-radius:14px;background:linear-gradient(145deg,#f6fbfc,#f0faf5)}.backend-market-ideas-section>header{display:flex;align-items:flex-start;justify-content:space-between;gap:12px;margin-bottom:12px}.backend-market-ideas-section h2{margin:2px 0 0;color:#0b5570;font-size:var(--text-title3)}.backend-market-idea-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(210px,1fr));gap:10px}.backend-market-idea-card{padding:13px;border:1px solid #c2dfdc;border-radius:12px;background:#fff}.backend-market-idea-card h3{margin:0 0 9px;color:#0b5570}.backend-market-idea-card ol{display:grid;gap:0;margin:0;padding:0;list-style:none;counter-reset:market-rank}.backend-market-idea-card li{counter-increment:market-rank;display:grid;grid-template-columns:24px minmax(64px,.7fr) 1fr;gap:2px 8px;padding:7px 4px;border-bottom:1px solid #e1eeec}.backend-market-idea-card li::before{content:counter(market-rank);grid-column:1;grid-row:1/3;align-self:center;color:#078363;font-size:var(--text-caption);font-weight:900}.backend-market-idea-card b{grid-column:2;color:#123f51}.backend-market-idea-card span{grid-column:3;color:#08745c;font-weight:800;text-align:right}.backend-market-idea-card small{grid-column:2/4;color:#607a82;text-align:right}.backend-market-idea-card p{color:#607a82}.backend-fred-grid,.backend-fred-disclaimer{display:none}
@media (max-width: 760px){.backend-analysis-view{padding:10px}.backend-analysis-shell{padding:16px;border-radius:17px}.backend-analysis-header,.backend-analysis-section-heading,.backend-analysis-hero{align-items:stretch;flex-direction:column}.backend-analysis-hero{padding:20px}.backend-analysis-hero h2{font-size:var(--text-title)}.backend-analysis-hero label{min-width:0}.backend-analysis-section{padding:16px}.backend-analysis-terms{grid-template-columns:1fr 1fr}.backend-analysis-metrics{justify-content:flex-start}.backend-analysis-paths>div{grid-template-columns:1fr}.backend-market-resources>summary,.backend-market-resources-body{padding:16px}.backend-market-controls{align-items:stretch;flex-direction:column}.backend-market-controls label,.backend-market-controls button{width:100%}.backend-market-widget iframe{height:430px}.backend-market-context-grid,.backend-market-idea-grid{grid-template-columns:1fr}.backend-market-context-card li{grid-template-columns:1fr}.backend-market-context-card>header,.backend-market-ideas-section>header{display:grid}}@media (max-width: 460px){.backend-analysis-terms{grid-template-columns:1fr}.backend-analysis-header .backend-analysis-back{width:100%}.backend-market-widget iframe{height:380px}}
@media (max-width: 460px){.backend-analysis-underlyings-term{grid-column:1}}

.hotlist-panel{margin:0 0 18px}.hotlist-panel>details{border:1px solid #96c9c2;border-radius:16px;background:#f5fbfa}.hotlist-panel>details>summary{cursor:pointer;padding:15px 20px;color:#0b5570;font-size:var(--text-headline);font-weight:900}.hotlist-panel>details[open]>summary{border-bottom:1px solid #c7e0dc}.hotlist-body{padding:16px 20px}.hotlist-note{margin:0 0 12px;color:#58747b;line-height:1.55}.hotlist-consent{display:flex;align-items:flex-start;gap:9px;padding:12px;border:1px solid #b7d9d5;border-radius:11px;background:#fff;color:#315c68;line-height:1.55}.hotlist-consent input{flex:none;margin-top:4px}.hotlist-controls{display:flex;align-items:end;flex-wrap:wrap;gap:10px;margin-top:13px}.hotlist-controls label{display:grid;gap:5px;color:#315c68;font-weight:800}.hotlist-controls select{min-height:44px;padding:8px 10px;border:1px solid #87c3ba;border-radius:8px;background:#fff;color:#164b5e;font:inherit}.hotlist-controls button{min-height:44px}.hotlist-status{min-height:1.4em;margin:10px 0 0;color:#416b78;font-weight:700}.hotlist-widget:empty{display:none}.hotlist-widget iframe{display:block;width:100%;height:520px;border:1px solid #b7d9d5;border-radius:12px;background:#fff}.hotlist-fallback{margin:12px 0 0;color:#607a82;font-size:var(--text-footnote)}.hotlist-fallback a{color:#08745c;font-weight:800}
@media (max-width: 600px){.hotlist-controls{display:grid;grid-template-columns:1fr}.hotlist-widget iframe{height:420px}}
.hotlist-exchanges{align-self:center;padding:6px 10px;border-radius:999px;background:#e4f6f1;color:#08745c;font-size:var(--text-footnote);font-weight:800}.hotlist-screens{display:flex;flex-wrap:wrap;gap:8px;margin-top:12px}.hotlist-screens a{display:inline-flex;align-items:center;min-height:38px;padding:7px 13px;border:1px solid #9fcfca;border-radius:999px;background:#fff;color:#0b5570;font-size:var(--text-footnote);font-weight:800;text-decoration:none}@media (hover:hover) and (pointer:fine){.hotlist-screens a:hover,.hotlist-screens a:focus-visible{background:#e4f6f1;border-color:#078464}}
@media (max-width: 600px){.hotlist-exchanges{align-self:start}.hotlist-screens a{flex:1 1 45%;justify-content:center}}

/* ---- Accessibility and motion, applied last so they win over the visual rules above. ---- */
/* A visible focus ring on keyboard navigation only. Mouse users never see it, keyboard users
   always do — the previous rules removed outlines on some controls without replacing them. */
:where(button,a,select,input,summary,[tabindex]):focus-visible {
  outline: 2.5px solid var(--accent);
  outline-offset: 2px;
  border-radius: var(--r-control);
}
/* Honour the OS "reduce motion" setting rather than animating regardless. The spinner keeps a
   slow rotation instead of stopping, because a frozen spinner reads as a hung button. */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .01ms !important; animation-iteration-count: 1 !important;
    transition-duration: .01ms !important; scroll-behavior: auto !important;
  }
  .quote-image-button.is-loading::before {
    animation: spin 1.6s linear infinite !important; animation-duration: 1.6s !important;
    animation-iteration-count: infinite !important;
  }
}

/* ---- Cloudflare-mode surfaces (rendered by backend-client.js) ----
   Same design language as the static page. Only visual properties are set: every class name and
   the DOM that backend-client.js builds are untouched, so login, submission, ranking and the quote
   image behave exactly as before. Placed last so these win over the rules above without !important. */
.backend-dialog { border-radius: var(--r-sheet); box-shadow: var(--shadow-3); }
.backend-dialog::backdrop { background: #00000052; backdrop-filter: blur(12px) saturate(140%); -webkit-backdrop-filter: blur(12px) saturate(140%); }
.backend-panel { padding: 26px; background: var(--bg-elevated); }
.backend-panel label { color: var(--label-2); font-weight: 600; }
.backend-panel input,
.backend-analysis-spot-card input,
.backend-account-lookup input {
  min-height: 44px; padding: 11px 13px; border: 1px solid var(--separator-solid);
  border-radius: var(--r-control); background: var(--bg-elevated); color: var(--label);
  transition: border-color .15s var(--ease), box-shadow .15s var(--ease);
}
.backend-panel input:focus,
.backend-analysis-spot-card input:focus,
.backend-account-lookup input:focus { outline: 0; border-color: var(--accent); box-shadow: 0 0 0 3.5px #0a7c8a2e; }
.backend-error { color: var(--tint-red); }

/* Cards and panels: one elevation, one radius, no competing borders. */
.backend-userbar { border: 0; border-radius: var(--r-card); background: #ffffffeb; backdrop-filter: blur(20px) saturate(180%); -webkit-backdrop-filter: blur(20px) saturate(180%); box-shadow: var(--shadow-2); color: var(--label); }
.ranking-card,
.backend-timeline-card,
.backend-rfq-card,
.backend-market-context-card,
.backend-analysis-section,
.backend-artifact-preview-card,
.backend-health-grid article { border: 0; border-radius: var(--r-card); background: var(--bg-elevated); box-shadow: var(--shadow-1); }
.backend-rfq-card { border-left: 4px solid var(--accent); }
.backend-rfq-card.status-completed { border-left-color: var(--teal-green); }
.backend-rfq-card.status-no_valid_quote,
.backend-rfq-card.status-failed,
.backend-rfq-card.status-cancelled { border-left-color: var(--tint-red); }

/* Table headers across the backend panels share the quote table's teal. */
.ranking-card th,
.backend-registration-list th,
.backend-accounts-list th,
.backend-archive-list th,
.backend-analysis-table-wrap th { background: var(--accent); color: #fff; font-weight: 600; }

/* Status chips and pills. */
.issuer-state { border: 0; border-radius: var(--r-control); background: var(--bg-inset); color: var(--label-2); }
.status-valid_reply { border: 0; background: #128a6a1f; color: #0e6e54; }
.status-timeout, .status-parse_error { border: 0; background: #d1352b14; color: #a82a22; }
.backend-rfq-meta span,
.backend-timeline-metrics span,
.backend-analysis-metrics span { border-radius: var(--r-pill); background: var(--bg-inset); color: var(--label-2); }

/* Every backend control reaches the same 44px target as the static page. */
.backend-panel button,
.backend-userbar button,
.artifact-request,
.backend-registration-actions button,
.backend-rfq-card footer button { min-height: 44px; border-radius: var(--r-control); font-weight: 600; }
.backend-registration-actions button,
.artifact-request { min-height: 38px; }

/* The analysis view is a full-screen sheet; give it the grouped background rather than a gradient. */
.backend-analysis-view { background: var(--bg-grouped); }
.backend-analysis-shell { border: 0; border-radius: var(--r-sheet); background: var(--bg-elevated); box-shadow: var(--shadow-1); }
.backend-analysis-hero { border-radius: var(--r-card); background: linear-gradient(135deg, #0b6b7a, #0a7c8a 55%, #12909a); }
.backend-analysis-terms > span { border-radius: var(--r-control); background: var(--bg-inset); color: var(--label-2); }
.backend-analysis-terms b { color: var(--label); }

/* ================================ Dark appearance ================================
   Follows the OS setting, the way an Apple app does. Tokens carry most of it; the rules below
   catch the surfaces whose colours predate the token system and are still written literally.

   The exception that matters: .quote-sheet is rasterised by html2canvas from what is on screen.
   If it followed the theme, a user in dark mode would hand a client a black quote card. It is
   pinned to its light appearance here, and must stay pinned. */
:root { color-scheme: light dark; }

/* Appearance picker ------------------------------------------------------------------------
   Three states rather than two: an explicit choice has to be able to lose to the OS again, and
   "auto" is the state the page shipped with. The stored value drives a media attribute on the
   dark stylesheet, so with JavaScript disabled the control simply never appears and the OS
   setting still applies. */
.theme-bar { display:flex; justify-content:flex-end; align-items:center; gap:10px; margin:0 0 12px; }
.theme-bar > span{ color:var(--label-2); font-size:var(--text-footnote); font-weight:600; letter-spacing:.02em; }
.theme-switch { display:inline-flex; gap:2px; padding:2px; border-radius:var(--r-pill); background:#7676801f; }
.theme-switch button{
  min-height:36px; padding:6px 15px; border:0; border-radius:var(--r-pill); background:transparent;
  /* Not --label-2: the unselected segment sits on the translucent track, not on the page, and the
     secondary token lands at 4.4:1 there. */
  color:#4a4a52; font:inherit; font-size:var(--text-footnote); font-weight:600; cursor:pointer;
  transition:background .18s ease, color .18s ease;
}
@media (hover:hover) and (pointer:fine){.theme-switch button:hover{ color:var(--label); }}
.theme-switch button[aria-pressed="true"] {
  background:var(--bg-elevated); color:var(--label); box-shadow:0 1px 3px #0000002e;
}
.theme-switch button:focus-visible { outline:2px solid var(--accent); outline-offset:2px; }
@media (max-width: 760px) {
  .theme-bar { justify-content:center; }
  .theme-switch { flex:1; }
  .theme-switch button { flex:1; min-height:44px; }
}

/* Validation uses text as well as colour and reveals fixed fields when the server rejects them. */
#quoteTable .field-error { color:var(--tint-red); font-size:var(--text-caption); line-height:1.45; overflow-wrap:anywhere; }
#quoteTable .quote-field.validation-reveal { display:table-cell!important; scroll-margin-block:150px; }
#quoteTable input.invalid, #quoteTable select.invalid { background:var(--bg-elevated)!important; }
#status { white-space:pre-line; }
@media (max-width:760px) {
  #quoteTable .quote-field.validation-reveal { display:block!important; }
}

/* Touch and reading sizes on phones ---------------------------------------------------------
   Measured at 375 px rather than assumed. Desktop density is deliberately left alone: a mouse
   does not need a 44 px target, and the 21-column table is dense on purpose. */
@media (max-width: 760px) {
  /* Five controls missed the 44 px minimum. The consent checkbox was the worst at 13x13 — a
     default checkbox that nothing had ever sized. */
  .hotlist-consent input { width:22px; height:22px; }
  .link-button { display:inline-flex; align-items:center; min-height:44px; padding:0 6px; vertical-align:middle; }
  .back-link { display:inline-flex; align-items:center; min-height:44px; }
  .hotlist-screens a { min-height:44px; }
  .trade-shortcut { min-height:44px; }

  /* .field-label-text is the label that tells you which field you are filling once the table
     becomes stacked cards, and there are 17 of them on screen at 11.8px. The #quoteTable prefix is
     required, not decorative: the rule it has to beat is #quoteTable .field-label-text, and an ID
     wins on specificity no matter how late this appears. */
  #quoteTable .field-label-text{ font-size:var(--text-footnote); }
  /* The navigator hint states which fixed values are being submitted on your behalf. */
  .trade-navigator p{ font-size:var(--text-caption); }
  .eyebrow{ font-size:var(--text-caption); }
  .field-group-legend span{ font-size:var(--text-caption); }
}

/* Collapsible user panel at every width -------------------------------------------------------
   The collapse used to be mobile-only; tablet and desktop always showed the whole bar. It now
   behaves the same at every width: collapsed shows 我的詢價 and the toggle and nothing else.
   The .backend-mobile-* class and id names are historical — the behaviour is no longer
   mobile-only, and renaming them would touch the generated markup, the CSS and the JS together
   for no functional gain. The <=760px block keeps its own expanded layout (a two-column grid
   pinned across the screen); this block only governs the collapsed state and the toggle. */
.backend-mobile-menu-toggle {
  display:inline-flex; align-items:center; justify-content:center;
  width:auto; min-width:58px; min-height:44px; padding:8px 10px;
}
.backend-userbar:not(.is-expanded) .backend-mobile-collapsible { display:none!important; }
.backend-userbar.is-expanded .backend-mobile-toggle-icon { transform:rotate(180deg); }

/* Earnings-date advisory ----------------------------------------------------------------------
   Advisory, not an error: it warns about timing, it never means the trade was rejected. Amber
   rather than red for that reason. It sits directly under the workspace header so it is in the
   same eyeline as the underlying that triggered it. */
.earnings-advisory {
  margin: 0 0 16px; padding: 14px 16px; border-left: 4px solid #c47a2c;
  border-radius: var(--r-control); background: #fff4e6; color: #6b4415; line-height: 1.55;
}
.earnings-advisory[hidden] { display: none; }
.earnings-advisory p { margin: 0; }
.earnings-advisory-lead{ font-weight: 700; font-size:var(--text-callout); }
.earnings-advisory-list {
  display: flex; flex-wrap: wrap; gap: 8px; margin: 10px 0 0; padding: 0; list-style: none;
}
.earnings-advisory-list li{
  display: flex; align-items: baseline; gap: 8px; padding: 6px 11px;
  border-radius: var(--r-pill); background: #ffffffcc; font-size:var(--text-subheadline);
}
.earnings-advisory-list b { font-weight: 700; }
.earnings-advisory-list span { color: #7a5423; }
.earnings-advisory-note{ margin-top: 9px; font-size:var(--text-footnote); }
/* A failed lookup must read as "unknown", never as an all-clear. */
.earnings-advisory-unavailable { margin-top: 9px; font-weight: 700; }

/* Undo and resume bars, and the advisory's jump target -----------------------------------------
   Both bars sit directly under the status line, where the eye already goes after an action. They
   are transient, so they must not shift the table the moment they appear and again when they go —
   hence a fixed min-height on the slot rather than a collapsing element. */
.undo-bar, .resume-bar{
  display: flex; flex-wrap: wrap; align-items: center; gap: 12px;
  margin: 0 0 14px; padding: 11px 15px;
  border-radius: var(--r-control); font-size:var(--text-subheadline);
}
.undo-bar[hidden] { display: none; }
.undo-bar { background: var(--bg-inset); color: var(--label); }
.resume-bar { background: #fff4e6; color: #6b4415; border-left: 4px solid #c47a2c; }
.undo-bar > span, .resume-bar > span { flex: 1 1 240px; }
.undo-bar-action, .resume-bar-action, .resume-bar-dismiss {
  min-height: 36px; padding: 6px 14px; border-radius: var(--r-control);
  font: inherit; font-weight: 600; cursor: pointer;
}
.undo-bar-action { border: 0; background: var(--accent); color: #fff; }
.resume-bar-action { border: 0; background: #a2601f; color: #fff; }
.resume-bar-dismiss { border: 1px solid #c9a77a; background: transparent; color: #6b4415; }
@media (max-width: 760px) {
  .undo-bar-action, .resume-bar-action, .resume-bar-dismiss { min-height: 44px; flex: 1; }
}

/* The advisory entries are buttons back to the field that produced them. */
.earnings-advisory-jump{
  display: flex; align-items: baseline; gap: 8px;
  padding: 6px 11px; border: 0; border-radius: var(--r-pill);
  background: #ffffffcc; color: inherit; font: inherit; font-size:var(--text-subheadline);
  cursor: pointer; text-align: left;
}
@media (hover:hover) and (pointer:fine){.earnings-advisory-jump:hover{ background: #fff; }}
.earnings-advisory-list li { padding: 0; background: none; }
/* Brief highlight so the field is findable once the scroll lands. */
.field-flash { box-shadow: 0 0 0 3px var(--accent); }
@media (prefers-reduced-motion: reduce) { .field-flash { box-shadow: 0 0 0 3px var(--accent); } }

/* Results: submitted terms, and the row view that sits beside the card view.
   Both were added together because they answer the same question from opposite ends -- "what did
   I actually ask for?" during the wait, and "how do the trades compare?" once quotes land. */

/* Segmented control. Two states, so aria-pressed carries the meaning and the styling follows it
   rather than a separate class that could drift out of sync with the attribute. */
.backend-results-view { display: inline-flex; padding: 2px; border-radius: var(--r-pill); background: var(--bg-inset); }
.backend-results-view button {
  min-height: 32px; padding: 4px 14px; border: 0; border-radius: var(--r-pill);
  background: none; color: var(--label-2); font: inherit; font-weight: 650; cursor: pointer;
}
.backend-results-view button[aria-pressed="true"] { background: var(--bg-elevated); color: var(--label); box-shadow: var(--shadow-1); }

/* Terms read back to the requester while the issuers are still replying. */
.ranking-terms { display: flex; flex-wrap: wrap; gap: 8px; margin: 0 0 14px; padding: 0; }
.ranking-terms > div {
  display: grid; gap: 1px; padding: 6px 11px; border-radius: var(--r-control); background: var(--bg-inset);
}
.ranking-terms dt{ font-size:var(--text-caption2); font-weight: 650; color: var(--label-3); }
.ranking-terms dd{ margin: 0; font-size:var(--text-subheadline); font-weight: 700; color: var(--label); font-variant-numeric: tabular-nums; }
/* Upfront is the term the desk reads first, so it is the one term that is not a quiet chip. */
.ranking-terms .is-upfront { background: var(--accent-soft); }
.ranking-terms .is-upfront dt { color: var(--accent-strong); }
.ranking-terms .is-upfront dd{ font-size:var(--text-callout); color: var(--accent-strong); }

/* Row view. 25 columns will not fit any dialog, so the table scrolls inside its own container and
   the trade code stays pinned -- without it the rank columns lose their subject. */
.ranking-table-note{ margin: 0 0 12px; color: var(--label-2); font-size:var(--text-subheadline); }
.ranking-table-hint{ display: block; color: var(--label-3); font-size:var(--text-footnote); }
/* Row-view export controls. These are screen chrome, not a render surface, so they stay on the
   tokens and follow the theme picker; the exported sheet carries its own inline light palette. */
.ranking-table-actions{ display: flex; flex-wrap: wrap; align-items: center; gap: 10px; margin: 0 0 12px; }
.ranking-table-actions label{ color: var(--label-2); font-size:var(--text-subheadline); font-weight: 600; }
.ranking-table-actions select{ min-height: 44px; padding: 8px 12px; border: 1px solid var(--separator-solid); border-radius: var(--r-control); background: var(--bg-elevated); color: var(--label); }
.ranking-table-actions button{ min-height: 44px; }
.ranking-table-actions .ranking-table-hint{ flex: 1 0 100%; }
.ranking-table-scroll { overflow-x: auto; border-radius: var(--r-card); background: var(--bg-elevated); box-shadow: var(--shadow-1); }
.ranking-table{ width: 100%; border-collapse: separate; border-spacing: 0; font-size:var(--text-footnote); white-space: nowrap; }
.ranking-table th, .ranking-table td { padding: 9px 12px; border-bottom: 1px solid var(--separator); text-align: left; }
.ranking-table thead th { position: sticky; top: 0; z-index: 2; background: var(--teal-deep); color: #fff; font-weight: 650; }
/* The corner has to pin on both axes or it drifts away from the trade codes it labels, which are
   pinned to the left. Opaque already, from the header rule above. */
.ranking-table thead th:first-child { left: 0; z-index: 3; }
.ranking-table tbody th {
  position: sticky; left: 0; z-index: 1; background: var(--bg-elevated);
  font-weight: 750; color: var(--label); box-shadow: 1px 0 0 var(--separator-solid);
}
.ranking-table tbody tr:last-child th, .ranking-table tbody tr:last-child td { border-bottom: 0; }
.ranking-table .term-upfront { background: var(--accent-soft); font-weight: 700; }
.ranking-table thead .term-upfront { background: var(--accent-strong); color: #fff; }
/* The priced field is blank on purpose; it must not read as a gap in the data. */
.ranking-table .term-target { color: var(--accent-strong); font-style: italic; }
.ranking-table .rank-col { background: var(--teal-core); }
.ranking-table .rank-cell { min-width: 118px; }
.ranking-table .rank-cell.is-empty { color: var(--label-3); }
.ranking-table .rank-issuer { display: block; font-weight: 700; color: var(--label); }
.ranking-table .rank-value { display: block; color: var(--label-2); font-variant-numeric: tabular-nums; }

@media (max-width: 760px) {
  /* Flex made the last row stretch, so a single leftover chip took the full width and the block
     stopped reading as a set. A grid keeps every chip the same size however many there are. */
  .ranking-terms { display: grid; grid-template-columns: repeat(auto-fit, minmax(96px, 1fr)); }
  .ranking-table-scroll { border-radius: 0; }
}

/* ==========================================================================
   Touch, safe area and sheet presentation — phone and tablet
   --------------------------------------------------------------------------
   This block exists because "responsive" and "native-feeling" are different
   problems. The layout already reflowed correctly at every width; what it did
   not do was behave like something built for a finger. Four specific gaps,
   each measured before it was fixed: no page declared viewport-fit, so every
   env(safe-area-inset-*) in the file resolved to 0; only three :active states
   existed, so a tap produced no feedback at all; no rule suppressed the grey
   tap flash; and hover styles were unguarded, so on touch they latched after
   a tap and only cleared on the next tap elsewhere. That last one is fixed at
   each rule via @media (hover:hover) and (pointer:fine).
   ========================================================================== */

/* iOS inflates text in landscape unless told not to. It looks like a rendering
   bug and is impossible to reproduce on a desktop browser. */
html { -webkit-text-size-adjust: 100%; text-size-adjust: 100%; }

/* Safe area. Inert without viewport-fit=cover on the page, which is why the
   meta tag and this block have to ship together. */
body { padding-left: env(safe-area-inset-left, 0px); padding-right: env(safe-area-inset-right, 0px); }
.app-shell, .guide-shell, .backend-analysis-shell { padding-bottom: max(var(--sp-6), env(safe-area-inset-bottom, 0px)); }
.trade-navigator { top: env(safe-area-inset-top, 0px); }

/* Anchor jumps must clear the sticky trade navigator, or the field you were
   sent to lands underneath it. */
html { scroll-padding-top: calc(var(--sp-8) + env(safe-area-inset-top, 0px)); }

@media (pointer: coarse) {
  /* Our own press feedback replaces the platform flash. Removing the flash
     without providing a replacement is worse than leaving it. */
  a, button, summary, [role="button"], input, select, textarea { -webkit-tap-highlight-color: transparent; }

  button, .guide-link, .back-link, .link-button, [role="button"],
  .theme-switch button, .backend-results-view button, .artifact-request {
    min-height: var(--tap-min);
  }
  /* Controls that sit inside dense tables keep their compact box but still
     take a full-size touch area via padding rather than height. */
  .artifact-request { padding-inline: var(--sp-3); }

  /* Immediate, physical, and short. iOS confirms a touch before the action
     completes; a transition longer than ~120ms reads as lag, not as motion. */
  button:active, .guide-link:active, .back-link:active,
  [role="button"]:active, .theme-switch button:active,
  .backend-results-view button:active {
    transform: scale(.97);
    opacity: .88;
    transition-duration: .06s;
  }

  /* A horizontal table scroll must not hand the gesture to the browser's
     back-swipe once it reaches the end. */
  .table-scroll, .ranking-table-scroll, .guide-table-scroll,
  .backend-archive-list, .backend-accounts-list, .backend-registration-list {
    overscroll-behavior-inline: contain;
    -webkit-overflow-scrolling: touch;
  }
}

/* Sheet presentation. On a phone a modal that floats in the middle of the
   screen reads as a web dialog; the platform convention is a sheet anchored to
   the bottom edge with a grabber. Tablet and desktop keep the centred card,
   which is also the platform convention there. */
@media (max-width: 760px) {
  dialog.backend-dialog {
    position: fixed;
    inset: auto 0 0 0;
    width: 100%;
    max-width: 100%;
    max-height: 92dvh;
    margin: 0;
    border-radius: var(--r-sheet) var(--r-sheet) 0 0;
    animation: sheet-rise .32s var(--ease);
  }
  dialog.backend-dialog .backend-panel {
    min-width: 0;
    max-height: 92dvh;
    overflow-y: auto;
    overscroll-behavior: contain;
    padding: var(--sp-6) var(--sp-4);
    padding-bottom: max(var(--sp-6), env(safe-area-inset-bottom, 0px));
    border-radius: var(--r-sheet) var(--r-sheet) 0 0;
  }
  /* The grabber is the affordance that says "this sheet moves". It is drawn,
     not interactive: dismissal stays with the existing close buttons, because
     a real drag-to-dismiss would need JS and a new way to close a dialog that
     the rest of the flow does not know about. */
  dialog.backend-dialog .backend-panel::before {
    content: "";
    display: block;
    width: 36px;
    height: 5px;
    margin: 0 auto var(--sp-4);
    border-radius: var(--r-pill);
    background: var(--label-3);
  }
  /* The quote-image preview needs no exception here. It is a <section role="dialog"> built in
     backend-image.mjs, not a <dialog class="backend-dialog">, so none of the rules above reach
     it and it keeps its own full-screen overlay. Do not "fix" these selectors to include it:
     the preview is a viewer, not a sheet. */
}

@keyframes sheet-rise { from { transform: translateY(100%); } to { transform: translateY(0); } }

.quote-sheet.theme-hsbc { --issuer-color:#db0011; --issuer-accent:#3a3a3a; --issuer-soft:#f9ecee; }
.issuer-pick.is-disabled { opacity:.5; cursor:not-allowed; }

@media (prefers-reduced-motion: reduce) {
  dialog.backend-dialog { animation: none; }
}
