/* In-match HUD (SPEC 14). All sizes use --u (scaled px) and --t (scaled text px). */

.ds-hud {
    position: absolute;
    inset: 0;
    pointer-events: none;
    opacity: var(--hud-alpha);
    text-shadow: var(--shadow-text);
}

.ds-region {
    position: absolute;
}

.ds-top-left { left: calc(28 * var(--u)); top: calc(24 * var(--u)); }
.ds-top-right {
    right: calc(28 * var(--u));
    top: calc(24 * var(--u));
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    gap: calc(8 * var(--u));
}
/* The top-centre column flows (compass, score bar, objective strip, connection
   banner, safe zone, notices, medal callout) and stops short of the crosshair:
   when it runs out of room the oldest notice lines give way (.ds-notices), the
   rest never overlap. */
.ds-top-center {
    left: 50%;
    top: calc(8 * var(--u));
    /* Height: stop short of the crosshair. Width: clear of the killfeed on the
       right (and the minimap on the left), never narrower than the compass. */
    max-height: calc(50% - 50 * var(--u));
    width: max-content;
    max-width: max(calc(100% - 1120 * var(--u)), calc(560 * var(--u)));
    transform: translateX(-50%);
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: calc(6 * var(--u));
}
.ds-top-center > * { flex: none; max-width: 100%; }
.ds-bottom-right { right: calc(40 * var(--u)); bottom: calc(34 * var(--u)); }
.ds-bottom-left { left: calc(28 * var(--u)); bottom: calc(28 * var(--u)); }

/* Below the crosshair: one flow column from just under the crosshair to the
   caption line. The prompts stack first (fixed order below); the score popup takes
   the room they leave (whole reason lines, fitted by popups.js); captions sit at
   the bottom. Nothing is placed at a fixed offset, so text size, wrapping and
   popup length can never print one element over another. */
.ds-lower {
    position: absolute;
    left: 50%;
    /* Starts clear of the hip crosshair's lower tick (a still hip gap of about 30 px plus
       the 10 px tick at 1080p), so objective status text never runs through it; the full
       stack still fits at 1080p (tests/game/ui-flow.test.js). */
    top: calc(50% + 52 * var(--u));
    bottom: calc(112 * var(--u));
    width: calc(640 * var(--u));
    max-width: calc(100% - 32px);
    transform: translateX(-50%);
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: calc(6 * var(--u));
}

.ds-prompts {
    flex: none;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: calc(6 * var(--u));
    max-width: 100%;
}

.ds-prompts > * { max-width: 100%; white-space: nowrap; }
.ds-prompts > .ds-target { order: 1; }
.ds-prompts > .ds-reload-prompt { order: 2; }
.ds-prompts > .ds-interact { order: 3; }
.ds-prompts > .ds-capture { order: 4; }
.ds-prompts > .ds-protected { order: 5; }

.ds-lower > .ds-captions {
    flex: 0 1 auto;
    min-height: 0;
    margin-top: auto;
    max-width: 100%;
    overflow: hidden;
    justify-content: flex-end;
}

/* ------------------------------------------------------------------ minimap */

.ds-minimap-frame {
    position: relative;
    width: calc(240 * var(--u));
    height: calc(240 * var(--u));
    clip-path: polygon(calc(14 * var(--u)) 0, 100% 0, 100% calc(100% - calc(14 * var(--u))), calc(100% - calc(14 * var(--u))) 100%, 0 100%, 0 calc(14 * var(--u)));
    background: rgba(8, 10, 9, 0.5);
}

.ds-minimap-frame::after {
    content: '';
    position: absolute;
    inset: 0;
    border: 1px solid rgba(236, 232, 220, 0.35);
    clip-path: inherit;
    pointer-events: none;
}

.ds-minimap-canvas {
    display: block;
    width: 100%;
    height: 100%;
}

.ds-minimap-floor {
    position: absolute;
    right: calc(8 * var(--u));
    bottom: calc(8 * var(--u));
    padding: calc(1 * var(--u)) calc(6 * var(--u));
    background: rgba(8, 10, 9, 0.8);
    border: 1px solid rgba(230, 204, 147, 0.45);
    color: var(--tan-2);
    font-size: calc(13 * var(--t));
    font-weight: 700;
    letter-spacing: 0.12em;
    text-shadow: none;
}

.ds-callout {
    margin-top: calc(8 * var(--u));
    max-width: calc(240 * var(--u));
    font-size: calc(18 * var(--t));
    font-weight: 700;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* No diamond outside a named room (uiState.callout is ''). */
.ds-callout-text:empty::before { display: none; }

.ds-callout-text::before {
    content: '';
    display: inline-block;
    width: calc(8 * var(--u));
    height: calc(8 * var(--u));
    margin-right: calc(8 * var(--u));
    border: calc(2 * var(--u)) solid var(--tan-2);
    transform: rotate(45deg) translateY(calc(-2 * var(--u)));
}

/* ------------------------------------------------------------------ compass and score bar */

.ds-compass-canvas {
    display: block;
    width: calc(560 * var(--u));
    height: calc(66 * var(--u));
}

.ds-scorebar {
    display: flex;
    align-items: stretch;
    gap: calc(6 * var(--u));
    margin-top: calc(-2 * var(--u));
}

.ds-side {
    position: relative;
    display: flex;
    align-items: center;
    gap: calc(10 * var(--u));
    width: calc(196 * var(--u));
    padding: calc(4 * var(--u)) calc(14 * var(--u)) calc(10 * var(--u));
    background: linear-gradient(90deg, rgba(8, 10, 9, 0) 0%, rgba(8, 10, 9, 0.7) 60%);
}

.ds-side-friend { justify-content: flex-end; color: var(--friend); }
.ds-side-enemy {
    flex-direction: row-reverse;
    justify-content: flex-end;
    color: var(--enemy);
    background: linear-gradient(270deg, rgba(8, 10, 9, 0) 0%, rgba(8, 10, 9, 0.7) 60%);
}

.ds-side-score {
    font-size: calc(38 * var(--t));
    font-weight: 700;
    line-height: 1;
    letter-spacing: 0.02em;
    transition: transform 0.2s;
}

.ds-side[data-lead='true'] .ds-side-score {
    transform: scale(1.08);
}

.ds-side-bar {
    position: absolute;
    left: calc(14 * var(--u));
    right: calc(14 * var(--u));
    bottom: calc(4 * var(--u));
    height: calc(4 * var(--u));
    background: rgba(242, 239, 230, 0.13);
    overflow: hidden;
}

.ds-side-fill {
    position: absolute;
    top: 0;
    bottom: 0;
    width: calc(var(--p, 0) * 100%);
    background: currentColor;
    box-shadow: 0 0 calc(8 * var(--u)) currentColor;
    transition: width 0.3s ease-out;
}

.ds-side-friend .ds-side-fill { right: 0; }
.ds-side-enemy .ds-side-fill { left: 0; }

.ds-team-chip {
    padding: calc(2 * var(--u)) calc(7 * var(--u));
    border: 1px solid currentColor;
    font-size: calc(13 * var(--t));
    font-weight: 700;
    letter-spacing: 0.16em;
    line-height: 1.2;
    text-shadow: none;
    background: rgba(8, 10, 9, 0.6);
}

.ds-team-chip[data-team='alpha'] { color: var(--tan-2); }
.ds-team-chip[data-team='beta'] { color: var(--green); }
.ds-team-chip[data-team='self'] { color: var(--friend); }
.ds-team-chip[data-team='leader'] {
    color: var(--enemy);
    max-width: calc(110 * var(--u));
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.ds-clock {
    min-width: calc(112 * var(--u));
    padding: calc(4 * var(--u)) calc(12 * var(--u)) calc(5 * var(--u));
    background: var(--panel);
    border-top: calc(2 * var(--u)) solid rgba(230, 204, 147, 0.7);
    text-align: center;
}

.ds-clock-time {
    font-size: calc(32 * var(--t));
    font-weight: 700;
    line-height: 1;
}

.ds-clock-limit {
    margin-top: calc(2 * var(--u));
    color: var(--muted);
    font-size: calc(11 * var(--t));
    letter-spacing: 0.18em;
    white-space: nowrap;
}

.ds-clock[data-urgent='true'] .ds-clock-time { color: var(--warn); }
.ds-clock[data-urgent='final'] .ds-clock-time { color: var(--enemy); animation: ds-pulse 1s ease-in-out infinite; }

/* ------------------------------------------------------------------ objective strip */

.ds-objective {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: calc(4 * var(--u));
    margin-top: calc(2 * var(--u));
}

.ds-obj-dom {
    display: flex;
    gap: calc(14 * var(--u));
}

.ds-zone-chip {
    --tone: var(--ink);
    --ring: var(--ink);
    position: relative;
    width: calc(40 * var(--u));
    height: calc(40 * var(--u));
    display: grid;
    place-items: center;
    transition: transform 0.2s;
}

.ds-zone-chip::before {
    content: '';
    position: absolute;
    inset: calc(6 * var(--u));
    transform: rotate(45deg);
    border: calc(2 * var(--u)) solid var(--tone);
    background: color-mix(in srgb, var(--tone) 22%, rgba(8, 10, 9, 0.82));
    box-shadow: 0 0 calc(10 * var(--u)) rgba(0, 0, 0, 0.6);
}

.ds-zone-chip::after {
    content: '';
    position: absolute;
    inset: calc(-3 * var(--u));
    border-radius: 50%;
    background: conic-gradient(var(--ring) calc(var(--p, 0) * 1turn), rgba(242, 239, 230, 0.12) 0);
    -webkit-mask: radial-gradient(circle, transparent calc(58% ), #000 calc(60%), #000 70%, transparent 71%);
    mask: radial-gradient(circle, transparent 58%, #000 60%, #000 70%, transparent 71%);
    opacity: 0;
}

.ds-zone-chip[data-ring]::after { opacity: 1; }
.ds-zone-chip[data-ring='friend'] { --ring: var(--friend); }
.ds-zone-chip[data-ring='enemy'] { --ring: var(--enemy); }
.ds-zone-chip[data-tone='friend'] { --tone: var(--friend); }
.ds-zone-chip[data-tone='enemy'] { --tone: var(--enemy); }
.ds-zone-chip[data-tone='contested'] { --tone: var(--contested); animation: ds-pulse 0.8s ease-in-out infinite; }
.ds-zone-chip[data-tone='neutral'] { --tone: rgba(242, 239, 230, 0.75); }
.ds-zone-chip[data-here='true'] { transform: scale(1.18); }

.ds-zone-letter {
    position: relative;
    z-index: 1;
    font-size: calc(19 * var(--t));
    font-weight: 700;
    line-height: 1;
}

.ds-obj-hp {
    display: flex;
    align-items: center;
    gap: calc(10 * var(--u));
    padding: calc(4 * var(--u)) calc(12 * var(--u));
    background: var(--panel);
}

.ds-hp-chip {
    --tone: rgba(242, 239, 230, 0.75);
    padding: calc(4 * var(--u)) calc(8 * var(--u));
    border: calc(2 * var(--u)) solid var(--tone);
    background: color-mix(in srgb, var(--tone) 22%, transparent);
    font-size: calc(16 * var(--t));
    font-weight: 700;
    letter-spacing: 0.1em;
}

.ds-hp-chip[data-tone='friend'] { --tone: var(--friend); }
.ds-hp-chip[data-tone='enemy'] { --tone: var(--enemy); }
.ds-hp-chip[data-tone='contested'] { --tone: var(--contested); animation: ds-pulse 0.8s ease-in-out infinite; }

.ds-hp-room { font-size: calc(16 * var(--t)); letter-spacing: 0.08em; text-transform: uppercase; }
.ds-hp-status { font-size: calc(12 * var(--t)); color: var(--muted); letter-spacing: 0.18em; }
.ds-hp-timer { font-size: calc(26 * var(--t)); font-weight: 700; min-width: calc(60 * var(--u)); text-align: right; }
.ds-hp-next { font-size: calc(13 * var(--t)); color: var(--tan-2); letter-spacing: 0.16em; }

.ds-obj-ctf { display: flex; gap: calc(10 * var(--u)); }

.ds-flag-status {
    --tone: rgba(242, 239, 230, 0.75);
    display: flex;
    align-items: center;
    gap: calc(8 * var(--u));
    padding: calc(4 * var(--u)) calc(12 * var(--u)) calc(4 * var(--u)) calc(10 * var(--u));
    background: var(--panel);
    border-bottom: calc(2 * var(--u)) solid var(--tone);
}

.ds-flag-status[data-tone='friend'] { --tone: var(--friend); }
.ds-flag-status[data-tone='enemy'] { --tone: var(--enemy); }

.ds-flag-glyph {
    position: relative;
    width: calc(14 * var(--u));
    height: calc(18 * var(--u));
}

.ds-flag-glyph::before {
    content: '';
    position: absolute;
    left: calc(1 * var(--u));
    top: 0;
    bottom: 0;
    width: calc(2 * var(--u));
    background: var(--tone);
}

.ds-flag-glyph::after {
    content: '';
    position: absolute;
    left: calc(3 * var(--u));
    top: 0;
    width: calc(11 * var(--u));
    height: calc(10 * var(--u));
    background: var(--tone);
    clip-path: polygon(0 0, 100% 45%, 0 100%);
}

.ds-flag-label { font-size: calc(12 * var(--t)); color: var(--muted); letter-spacing: 0.16em; }
.ds-flag-state { font-size: calc(16 * var(--t)); font-weight: 700; letter-spacing: 0.1em; color: var(--tone); }

.ds-obj-rag {
    display: flex;
    align-items: center;
    gap: calc(12 * var(--u));
    padding: calc(4 * var(--u)) calc(14 * var(--u));
    background: var(--panel);
}

.ds-rag-count { font-size: calc(22 * var(--t)); font-weight: 700; }
.ds-rag-sep { font-size: calc(12 * var(--t)); color: var(--muted); letter-spacing: 0.18em; }
.ds-rag-div { width: 1px; height: calc(18 * var(--u)); background: var(--line-2); }
.ds-tone-enemy { color: var(--enemy); }
.ds-tone-friend { color: var(--friend); }

.ds-safezone {
    margin-top: calc(6 * var(--u));
    padding: calc(6 * var(--u)) calc(18 * var(--u));
    background: rgba(14, 40, 20, 0.82);
    border: 1px solid rgba(74, 222, 128, 0.55);
    text-align: center;
}

.ds-safezone-title { font-size: calc(18 * var(--t)); font-weight: 700; letter-spacing: 0.24em; color: var(--mk-2); }
.ds-safezone-sub { font-size: calc(12 * var(--t)); letter-spacing: 0.18em; color: #cfe8d2; }

.ds-top-center > .ds-notices {
    /* The one item that yields when the column is short: the newest notices stay
       (bottom), older lines are clipped away at the top. */
    flex: 0 1 auto;
    min-height: 0;
    overflow: hidden;
    display: flex;
    flex-direction: column;
    justify-content: flex-end;
    align-items: center;
    gap: calc(3 * var(--u));
}

.ds-notices:empty { display: none; }
/* The slot adds no box (and no gap) of its own: the banner is the column's item. */
.ds-conn-slot { display: contents; }

.ds-notice {
    flex: none;
    max-width: 100%;
    /* Up to two centred lines (a hardpoint room name at 150% text is the part that
       matters); longer text ends in an ellipsis on the second line. */
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 2;
    line-clamp: 2;
    overflow: hidden;
    text-align: center;
    overflow-wrap: anywhere;
    line-height: 1.15;
    font-size: calc(19 * var(--t));
    font-weight: 700;
    letter-spacing: 0.18em;
    text-transform: uppercase;
    animation: ds-notice-in 0.3s cubic-bezier(0.2, 0.8, 0.2, 1) both, ds-toast-out 0.5s ease-in 3.1s forwards;
}

.ds-notice[data-kind='friend'] { color: var(--friend); }
.ds-notice[data-kind='enemy'], .ds-notice[data-kind='error'] { color: var(--enemy); }
.ds-notice[data-kind='objective'] { color: var(--tan-2); }
.ds-notice[data-kind='success'] { color: var(--mk-2); }

@keyframes ds-notice-in {
    from { opacity: 0; letter-spacing: 0.5em; }
}

/* ------------------------------------------------------------------ killfeed and net info */

.ds-netgraph {
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    gap: calc(3 * var(--u));
}

.ds-netgraph-text {
    display: flex;
    gap: calc(12 * var(--u));
    font-size: calc(13 * var(--t));
    letter-spacing: 0.12em;
    color: var(--ink-2);
    white-space: nowrap;
    font-variant-numeric: tabular-nums;
}

.ds-ng-value { margin-right: calc(3 * var(--u)); font-weight: 700; }
.ds-ng-fps .ds-ng-value { color: #7dff6a; }
.ds-ng-ping .ds-ng-value { color: #ffb347; }
.ds-ng-loss .ds-ng-value { color: #ff5a4a; margin-right: 0; }
.ds-netgraph-canvas { display: block; border: 1px solid var(--line); }

.ds-killfeed {
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    gap: calc(3 * var(--u));
}

.ds-kf-row {
    display: flex;
    align-items: center;
    gap: calc(8 * var(--u));
    padding: calc(3 * var(--u)) calc(10 * var(--u)) calc(3 * var(--u)) calc(28 * var(--u));
    background: linear-gradient(90deg, rgba(8, 10, 9, 0) 0%, rgba(8, 10, 9, 0.7) calc(26 * var(--u)));
    font-size: calc(17 * var(--t));
    font-weight: 600;
    line-height: 1.25;
    white-space: nowrap;
    animation: ds-kf-in 0.22s cubic-bezier(0.2, 0.8, 0.2, 1) both;
    transition: opacity 0.3s, transform 0.3s;
}

.ds-kf-row[data-self] {
    background: linear-gradient(90deg, rgba(201, 168, 106, 0) 0%, rgba(96, 78, 42, 0.78) calc(26 * var(--u)));
    box-shadow: inset calc(-3 * var(--u)) 0 0 var(--tan-2);
}

.ds-kf-row.is-dim { opacity: 0.55; }
.ds-kf-row.is-leaving { opacity: 0; transform: translateX(calc(14 * var(--u))); }

@keyframes ds-kf-in {
    from { opacity: 0; transform: translateX(calc(24 * var(--u))); }
}

.ds-kf-name { max-width: calc(170 * var(--u)); overflow: hidden; text-overflow: ellipsis; }
.ds-kf-name[data-rel='friend'] { color: var(--friend); }
.ds-kf-name[data-rel='enemy'] { color: var(--enemy); }
.ds-kf-name[data-rel='self'] { color: var(--self); }

/* Colour-blind presets: the own row is neutral grey with a white edge and the own
   name is white and underlined, so it cannot read as an amber/yellow enemy. */
.ds-ui:not([data-colorblind='off']) .ds-kf-row[data-self] {
    background: linear-gradient(90deg, rgba(90, 94, 100, 0) 0%, rgba(58, 62, 68, 0.85) calc(26 * var(--u)));
    box-shadow: inset calc(-3 * var(--u)) 0 0 #ffffff;
}

.ds-ui:not([data-colorblind='off']) .ds-kf-name[data-rel='self'],
.ds-ui:not([data-colorblind='off']) .ds-chat-name[data-rel='self'] {
    text-decoration: underline;
    text-decoration-thickness: calc(2 * var(--u));
    text-underline-offset: calc(3 * var(--u));
}

.ds-kf-tag {
    padding: 0 calc(4 * var(--u));
    color: var(--ink-2);
    font-size: calc(13 * var(--t));
    font-weight: 700;
    letter-spacing: 0.06em;
    border: 1px solid rgba(242, 239, 230, 0.25);
    text-shadow: none;
}

.ds-kf-revive { color: var(--mk-2); border-color: rgba(74, 222, 128, 0.45); }
.ds-kf-dist { color: var(--muted); font-size: calc(13 * var(--t)); }

/* ------------------------------------------------------------------ weapon panel */

.ds-weapon {
    --mag: 1;
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    gap: calc(3 * var(--u));
    min-width: calc(250 * var(--u));
}

.ds-weapon-head {
    display: flex;
    align-items: center;
    gap: calc(8 * var(--u));
    font-size: calc(17 * var(--t));
    letter-spacing: 0.12em;
    text-transform: uppercase;
}

.ds-firemode {
    padding: 0 calc(5 * var(--u));
    border: 1px solid rgba(230, 204, 147, 0.55);
    color: var(--tan-2);
    font-size: calc(12 * var(--t));
    font-weight: 700;
    letter-spacing: 0.12em;
    text-shadow: none;
}

.ds-firemode:empty { display: none; }

.ds-ammo {
    display: flex;
    align-items: baseline;
    line-height: 0.92;
}

.ds-ammo-mag { font-size: calc(64 * var(--t)); font-weight: 700; letter-spacing: -0.01em; }
.ds-ammo-sep { margin: 0 calc(6 * var(--u)); font-size: calc(30 * var(--t)); color: var(--dim); }
.ds-ammo-reserve { font-size: calc(28 * var(--t)); color: var(--ink-2); }
.ds-weapon[data-ammo='low'] .ds-ammo-mag { color: var(--warn); }
.ds-weapon[data-ammo='empty'] .ds-ammo-mag,
.ds-weapon[data-ammo='dry'] .ds-ammo-mag { color: var(--enemy); }

.ds-mag-bar {
    position: relative;
    width: calc(230 * var(--u));
    height: calc(5 * var(--u));
    background: rgba(242, 239, 230, 0.14);
    -webkit-mask: repeating-linear-gradient(90deg, #000 0 calc(6 * var(--u)), transparent calc(6 * var(--u)) calc(8 * var(--u)));
    mask: repeating-linear-gradient(90deg, #000 0 calc(6 * var(--u)), transparent calc(6 * var(--u)) calc(8 * var(--u)));
}

.ds-mag-fill {
    position: absolute;
    right: 0;
    top: 0;
    bottom: 0;
    width: calc(var(--mag) * 100%);
    background: var(--ink);
}

.ds-weapon[data-ammo='low'] .ds-mag-fill { background: var(--warn); }
.ds-weapon[data-ammo='empty'] .ds-mag-fill { background: var(--enemy); }

.ds-equip {
    display: flex;
    gap: calc(16 * var(--u));
    margin-top: calc(8 * var(--u));
}

.ds-equip-item {
    display: flex;
    align-items: center;
    gap: calc(7 * var(--u));
    font-size: calc(13 * var(--t));
    letter-spacing: 0.14em;
    color: var(--ink-2);
}

.ds-equip-item[data-empty] { opacity: 0.4; }

.ds-pips {
    display: inline-flex;
    gap: calc(4 * var(--u));
}

/* One pip per carried slot (class capacity); filled while the item is held. */
.ds-pip {
    width: calc(11 * var(--u));
    height: calc(11 * var(--u));
    border-radius: 50%;
    border: calc(2 * var(--u)) solid var(--ink);
    background: transparent;
    opacity: 0.45;
}

.ds-pip[data-full] { background: var(--ink); opacity: 1; }

.ds-equip-smoke .ds-pip {
    border-radius: calc(2 * var(--u));
    width: calc(9 * var(--u));
    height: calc(13 * var(--u));
}

.ds-tac {
    --p: 1;
    display: flex;
    align-items: center;
    gap: calc(8 * var(--u));
    margin-bottom: calc(4 * var(--u));
    font-size: calc(11 * var(--t));
    letter-spacing: 0.2em;
    color: var(--ink-2);
}

.ds-tac-bar {
    position: relative;
    width: calc(120 * var(--u));
    height: calc(4 * var(--u));
    background: rgba(242, 239, 230, 0.14);
}

.ds-tac-fill {
    position: absolute;
    left: 0;
    top: 0;
    bottom: 0;
    width: calc(var(--p) * 100%);
    background: var(--mk-2);
}

.ds-tac[data-state='low'] .ds-tac-fill { background: var(--warn); }

/* ------------------------------------------------------------------ centre prompts */

.ds-target {
    overflow: hidden;
    text-overflow: ellipsis;
    font-size: calc(16 * var(--t));
    font-weight: 700;
    letter-spacing: 0.06em;
}

.ds-target[data-rel='friend'] { color: var(--friend); }
.ds-target[data-rel='enemy'] { color: var(--enemy); }

.ds-reload-prompt {
    display: flex;
    align-items: center;
    gap: calc(8 * var(--u));
    font-size: calc(19 * var(--t));
    font-weight: 700;
    letter-spacing: 0.24em;
}

.ds-reload-prompt[data-tone='alert'] { color: var(--enemy); animation: ds-pulse 0.9s ease-in-out infinite; }
.ds-reload-prompt[data-tone='warn'] { color: var(--warn); }
.ds-reload-prompt[data-tone='info'] { color: var(--ink-2); }

.ds-popups {
    --o: 1;
    /* Fills the room the prompts and captions leave (its size never depends on its
       lines, so fitting them cannot feed back into the layout). */
    flex: 1 1 0;
    min-height: 0;
    max-width: 100%;
    overflow: hidden;
    display: flex;
    flex-direction: column;
    align-items: center;
    opacity: var(--o);
}

.ds-popups.is-clipped { visibility: hidden; }
/* The total always has room: when the column is short, older caption lines give
   way (they clip from the top) before the popup does. */
.ds-popups:not([hidden]) { min-height: calc(40 * var(--t)); }
.ds-popup-total { flex: none; }

.ds-popup-total {
    font-size: calc(36 * var(--t));
    font-weight: 700;
    color: var(--gold);
    line-height: 1;
}

.ds-popup-lines {
    display: flex;
    flex-direction: column;
    align-items: center;
    margin-top: calc(3 * var(--u));
}

.ds-popup-line {
    display: flex;
    white-space: nowrap;
    gap: calc(10 * var(--u));
    font-size: calc(15 * var(--t));
    letter-spacing: 0.14em;
    line-height: 1.3;
}

.ds-popup-line:first-child { font-size: calc(17 * var(--t)); }
.ds-popup-line:nth-child(n + 3) { opacity: 0.7; }
.ds-popup-points { color: var(--gold); }

.ds-interact {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: calc(5 * var(--u));
    width: calc(360 * var(--u));
    font-size: calc(18 * var(--t));
    letter-spacing: 0.14em;
    text-transform: uppercase;
}

/* One line: the key and the label; a long label ellipsises instead of wrapping. */
.ds-interact-line {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: calc(8 * var(--u));
    max-width: 100%;
    min-width: 0;
}

.ds-interact-line > .ds-keycap { flex: none; }
.ds-interact-text { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.ds-interact-bar {
    position: relative;
    flex: none;
    width: 100%;
    height: calc(6 * var(--u));
    background: rgba(242, 239, 230, 0.16);
}

.ds-interact-fill {
    position: absolute;
    inset: 0 auto 0 0;
    width: calc(var(--p, 0) * 100%);
    background: var(--mk-2);
}

.ds-capture {
    --tone: var(--ink);
    width: calc(340 * var(--u));
    text-align: center;
}

.ds-capture[data-tone='friend'] { --tone: var(--friend); }
.ds-capture[data-tone='enemy'] { --tone: var(--enemy); }
.ds-capture[data-tone='contested'] { --tone: var(--contested); }

.ds-capture-label {
    overflow: hidden;
    text-overflow: ellipsis;
    font-size: calc(19 * var(--t));
    font-weight: 700;
    letter-spacing: 0.22em;
    color: var(--tone);
}

.ds-capture-track {
    position: relative;
    height: calc(8 * var(--u));
    margin-top: calc(5 * var(--u));
    background: rgba(8, 10, 9, 0.7);
    border: 1px solid rgba(242, 239, 230, 0.25);
}

.ds-capture-fill {
    --fill: var(--tone);
    position: absolute;
    inset: 0 auto 0 0;
    width: calc(var(--p, 0) * 100%);
    background: var(--fill);
    box-shadow: 0 0 calc(10 * var(--u)) var(--fill);
}

/* Winding back the enemy's partial capture (objective-model captureStatus): their
   share drains in their colour under the local team's label. */
.ds-capture[data-fill='enemy'] .ds-capture-fill { --fill: var(--enemy); }

.ds-protected {
    display: flex;
    align-items: center;
    gap: calc(10 * var(--u));
    font-size: calc(14 * var(--t));
    letter-spacing: 0.2em;
    color: #cfe8d2;
}

.ds-protected-bar {
    position: relative;
    width: calc(80 * var(--u));
    height: calc(4 * var(--u));
    background: rgba(242, 239, 230, 0.16);
}

.ds-protected-fill {
    position: absolute;
    inset: 0 auto 0 0;
    width: calc(var(--p, 0) * 100%);
    background: var(--mk-2);
}
