blindspot / frontend /src /viewer /Viewer.module.css
yashwrites's picture
Signs on the film, draw tool, My search off by default, example films and Radiopaedia links (part 2)
2e6a666 verified
Raw History Blame Contribute Delete
22.6 kB
/* Viewer: PACS surround, film-black letterbox, amber = learner, cyan = expert truth (SPEC §14.1).
Three rows: a prompt strip, the film stage, the image controls. The strips never overlap the film. */
.viewer {
position: relative;
height: 100%;
min-height: 0;
display: flex;
flex-direction: column;
background: var(--pacs-surround);
}
.topStrip {
flex: 0 0 40px;
height: 40px;
display: flex;
align-items: center;
justify-content: space-between;
gap: 12px;
padding: 0 12px;
color: #c9d1d8;
font-size: var(--fs-1);
white-space: nowrap;
overflow: hidden;
}
:root[data-projector='1'] .topStrip { flex-basis: 48px; height: 48px; }
.stripLeft { min-width: 0; overflow: hidden; text-overflow: ellipsis; display: flex; align-items: center; }
.stripRight { display: flex; align-items: center; gap: 8px; flex-shrink: 0; }
.stripNote { color: #e6ebef; }
.stripArmed { color: #e6ebef; display: inline-flex; align-items: center; gap: 6px; }
.stripArmed strong { color: var(--grease-amber); font-weight: 700; }
.stripLink { background: none; border: none; color: #c9d1d8; text-decoration: underline; cursor: pointer; padding: 2px 4px; margin-left: 8px; font-size: var(--fs-1); }
.key { display: inline-flex; align-items: center; gap: 7px; color: #c9d1d8; }
.keyCyan, .keyAmber { display: inline-block; width: 18px; height: 0; border-top: 2px solid var(--lightbox-cyan); }
.keyAmber { border-top-color: var(--grease-amber); margin-left: 10px; }
.stage {
position: relative;
flex: 1 1 auto;
min-height: 0;
overflow: hidden;
touch-action: none;
user-select: none;
cursor: default;
outline: none;
}
.stage:focus-visible { box-shadow: inset 0 0 0 2px var(--grease-amber); }
.marking { cursor: crosshair; }
.panning { cursor: grabbing; }
.layer {
position: absolute;
left: 0;
top: 0;
transform-origin: 0 0;
}
/* The view eases back to the whole film as the reveal starts (part of the one animated moment). */
.fitting { transition: transform 360ms ease-out; }
.film {
position: absolute;
inset: -1px;
background: var(--film-black);
box-shadow: 0 0 0 1px #000;
}
.image, .trace {
position: absolute;
left: 0;
top: 0;
display: block;
pointer-events: none;
}
.trace {
opacity: 0.45;
image-rendering: auto;
mix-blend-mode: screen; /* reads as light where you looked, not a stain */
}
.overlay {
position: absolute;
left: 0;
top: 0;
overflow: visible;
pointer-events: none;
}
/* Marks: grease-pencil amber. Unfinished marks are dashed. Overcalls get a hollow ring after the reveal. */
.mark { cursor: grab; }
.markHalo { fill: none; stroke: rgba(0, 0, 0, 0.55); }
.markRing { fill: none; stroke: var(--grease-amber); }
.markDot { fill: var(--grease-amber); }
.markText {
fill: var(--grease-amber);
stroke: rgba(0, 0, 0, 0.75);
paint-order: stroke;
font-weight: 700;
}
.overcallRing {
fill: none;
stroke: var(--grease-amber);
stroke-opacity: 0.9;
}
/* Expert outlines: cyan. Labels are plain text on a solid dark pill. */
.outline {
fill: var(--lightbox-cyan);
fill-opacity: 0.07;
stroke: var(--lightbox-cyan);
stroke-linejoin: round;
}
.outlineHalo {
fill: none;
stroke: var(--lightbox-cyan);
stroke-opacity: 0.24;
stroke-linejoin: round;
}
.pill { fill: rgba(9, 11, 13, 0.88); }
.findingText { fill: var(--lightbox-cyan); font-weight: 700; }
.missChip { fill: none; stroke: var(--lightbox-cyan); }
.missChipText { fill: var(--lightbox-cyan); font-weight: 700; }
.arrow, .arrowCasing {
fill: none;
stroke: var(--grease-amber);
stroke-linecap: round;
stroke-linejoin: round;
}
.arrowCasing { stroke: rgba(0, 0, 0, 0.55); }
.arrowText { fill: var(--grease-amber); font-weight: 700; }
.unvisitedRing { fill: none; stroke: var(--grease-amber); stroke-opacity: 0.95; }
.ringText { fill: var(--grease-amber); font-weight: 700; }
/* ---- Reveal choreography (~1.2 s). The only self-starting motion in the app. ---- */
.revealTrace { animation: fadeTrace 320ms ease-out both; }
.revealRing { animation: fade 320ms ease-out 120ms both; }
.revealOutline {
stroke-dasharray: 1;
stroke-dashoffset: 1;
fill-opacity: 0;
animation: drawFill 480ms ease-in-out 300ms forwards;
}
.revealHalo { animation: haloPulse 1100ms ease-in-out 780ms both; }
.revealLabel { animation: fade 200ms ease-out 760ms both; }
.revealArrow {
stroke-dasharray: 1;
stroke-dashoffset: 1;
animation: draw 340ms ease-out 760ms forwards;
}
.revealArrowHead {
stroke-dasharray: 1;
stroke-dashoffset: 1;
animation: draw 120ms ease-out 1080ms forwards;
}
.revealArrowText { animation: fade 180ms ease-out 1020ms both; }
.settle { animation: fade 200ms ease-out 1100ms both; }
@keyframes fadeTrace { from { opacity: 0; } to { opacity: 0.45; } }
@keyframes fade { from { opacity: 0; } to { opacity: 1; } }
@keyframes draw { to { stroke-dashoffset: 0; } }
@keyframes drawFill {
80% { stroke-dashoffset: 0; fill-opacity: 0; }
to { stroke-dashoffset: 0; fill-opacity: 0.07; }
}
/* Two soft beats on a missed outline, then it rests as a faint halo. */
@keyframes haloPulse {
0% { stroke-opacity: 0; }
25% { stroke-opacity: 0.6; }
50% { stroke-opacity: 0.18; }
75% { stroke-opacity: 0.6; }
100% { stroke-opacity: 0.24; }
}
@media (prefers-reduced-motion: reduce) {
.revealTrace, .revealLabel, .revealArrowText, .settle, .revealRing, .revealHalo { animation: none; }
.revealOutline, .revealArrow, .revealArrowHead { animation: none; stroke-dashoffset: 0; stroke-dasharray: none; }
.revealOutline { fill-opacity: 0.07; }
.fitting { transition: none; }
}
/* Magnifier: 180 px, 2.5×. */
.loupe {
position: absolute;
left: 0;
top: 0;
display: none;
border-radius: 50%;
overflow: hidden;
pointer-events: none;
background: var(--film-black);
box-shadow: 0 0 0 1.5px rgba(140, 153, 166, 0.9), 0 0 0 4px rgba(0, 0, 0, 0.55), 0 6px 18px rgba(0, 0, 0, 0.5);
}
.loupeImg {
position: absolute;
left: 0;
top: 0;
max-width: none;
transform-origin: 0 0;
}
.loupeCross {
position: absolute;
left: 50%;
top: 50%;
width: 10px;
height: 10px;
margin: -5px 0 0 -5px;
border-radius: 50%;
border: 1px solid rgba(240, 169, 46, 0.8);
}
/* The armed finding rides with the cursor: amber, because it is the learner's call. */
.armedTag, .crosshairTag {
padding: 2px 9px;
border-radius: 999px;
background: var(--grease-amber);
color: #1d1300;
font-size: 14px;
font-weight: 700;
white-space: nowrap;
box-shadow: 0 0 0 1.5px rgba(0, 0, 0, 0.6);
pointer-events: none;
}
.armedTag { position: absolute; left: 0; top: 0; display: none; z-index: 3; }
/* Keyboard crosshair: amber with a dark casing so it shows on lung and on bone. */
.crosshair { position: absolute; left: -22px; top: -22px; width: 44px; height: 44px; pointer-events: none; z-index: 3; }
.crosshair::before, .crosshair::after {
content: '';
position: absolute;
background: var(--grease-amber);
box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.85);
}
.crosshair::before { left: 0; top: 21px; width: 44px; height: 2px; }
.crosshair::after { left: 21px; top: 0; width: 2px; height: 44px; }
.crosshairTag { position: absolute; left: 36px; top: 36px; }
.loading {
position: absolute;
left: 50%;
top: 45%;
transform: translateX(-50%);
color: #c9d1d8;
font-size: var(--fs-1);
pointer-events: none;
}
/* Image controls: their own strip under the film. */
.tools {
flex: 0 0 auto;
min-height: 46px;
display: flex;
align-items: center;
flex-wrap: wrap;
gap: 6px 10px;
padding: 6px 12px;
background: #15181a;
border-top: 1px solid #2a2f34;
color: #c9d1d8;
font-size: var(--fs-1);
}
.toolGroup { display: inline-flex; align-items: center; gap: 6px; }
.toolLabel { color: #c9d1d8; }
.toolSpacer { flex: 1 1 0; }
/* The tool group at the right end; when the strip wraps it keeps to the right on its own line. */
.toolRight { display: inline-flex; align-items: center; gap: 10px; margin-left: auto; }
.zoom { min-width: 2.9em; text-align: center; font-variant-numeric: tabular-nums; color: #e6ebef; }
.slider { display: flex; align-items: center; gap: 6px; }
.slider input { width: 64px; accent-color: var(--graticule); }
.tool, .toolSq {
display: inline-flex;
align-items: center;
gap: 6px;
background: transparent;
color: #e6ebef;
border: 1px solid #4a535c;
border-radius: var(--radius);
padding: 3px 9px;
cursor: pointer;
font-size: var(--fs-1);
white-space: nowrap;
}
.toolSq { width: 28px; height: 28px; padding: 0; justify-content: center; font-size: 18px; line-height: 1; }
.toolSq:disabled { opacity: 0.4; cursor: default; }
.tool:hover, .toolSq:hover:not(:disabled) { border-color: var(--graticule); }
.toolOn { background: #e6ebef; color: #111; border-color: #e6ebef; }
/* State is written in the label; the dot repeats it (hollow = off, amber = on). */
.dot { width: 8px; height: 8px; border-radius: 50%; background: transparent; box-shadow: inset 0 0 0 1.5px currentColor; opacity: 0.75; flex-shrink: 0; }
.toolOn .dot { opacity: 1; background: var(--grease-amber); box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.35); }
.viewer :is(button, input):focus-visible { outline: 2px solid var(--grease-amber); outline-offset: 2px; }
.tipAnchor { position: relative; display: inline-flex; }
.tip {
position: absolute;
right: 0;
bottom: calc(100% + 10px);
width: 290px;
padding: 9px 12px;
border-radius: var(--radius);
background: var(--report-paper);
color: var(--report-ink);
font-size: 14px;
line-height: 1.4;
white-space: normal;
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.5);
pointer-events: none;
z-index: 6;
}
.tip::after {
content: '';
position: absolute;
right: 28px;
top: 100%;
border: 7px solid transparent;
border-top-color: var(--report-paper);
}
.tip .kbdTool { border-color: #9aa5af; color: var(--report-ink); }
/* Mark popover: report paper on the dark surround, beside the mark with a thin connector. */
.connector { position: absolute; left: 0; top: 0; pointer-events: none; z-index: 4; overflow: visible; }
.connectorCasing { stroke: rgba(0, 0, 0, 0.7); stroke-width: 3.5; stroke-linecap: round; }
.connectorLine { stroke: var(--grease-amber); stroke-width: 1.5; stroke-linecap: round; }
.connectorDot { fill: var(--grease-amber); stroke: rgba(0, 0, 0, 0.7); stroke-width: 1; }
.popover {
position: absolute;
z-index: 5;
background: var(--report-paper);
color: var(--report-ink);
border-radius: var(--radius);
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.45);
padding: 12px 12px 10px;
font-size: var(--fs-1);
cursor: default;
outline: none;
}
.popover :is(button):focus-visible { outline: 2px solid #9a6200; outline-offset: 1px; }
.popHead { display: flex; gap: 8px; align-items: center; font-weight: 700; margin-bottom: 8px; }
.popId { color: #9a6200; }
.popChange { margin-left: auto; background: none; border: none; color: var(--report-ink-muted); text-decoration: underline; cursor: pointer; padding: 2px 0; font-weight: 400; font-size: 14px; }
.popLabels { display: grid; grid-template-columns: 1fr 1fr; gap: 4px 8px; }
.popLabelRow { display: flex; align-items: center; gap: 4px; min-width: 0; }
.popLabel {
flex: 1;
min-width: 0;
text-align: left;
border: 1px solid var(--report-rule);
background: #fff;
border-radius: 4px;
padding: 5px 8px;
cursor: pointer;
color: var(--report-ink);
font-size: var(--fs-1);
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.popLabel:hover { border-color: var(--grease-amber); }
.popLabelOn { background: var(--grease-amber); border-color: var(--grease-amber); color: #1d1300; font-weight: 700; }
.popNotSure { font-style: normal; color: var(--report-ink-muted); }
.popNotSure.popLabelOn { color: #1d1300; }
.popAsk { margin: 12px 0 6px; font-weight: 700; }
.popConfRow { display: flex; justify-content: center; }
.popKeys { margin: 8px 0 0; font-size: 13px; color: var(--report-ink-muted); text-align: center; }
.popKeys kbd { font: inherit; padding: 0 4px; border: 1px solid #b9c2ca; border-radius: 3px; background: #fff; }
.popFoot { display: flex; justify-content: space-between; align-items: center; gap: 8px; margin-top: 10px; }
.popMissing { font-size: 13px; color: #7a4d00; text-align: right; flex: 1; }
.popDelete { background: none; border: none; color: var(--report-ink-muted); text-decoration: underline; cursor: pointer; padding: 4px 0; }
.popDone {
background: var(--report-ink);
color: #fff;
border: none;
border-radius: var(--radius);
padding: 5px 16px;
cursor: pointer;
}
.popDone:disabled { opacity: 0.4; cursor: default; }
/* Read-only reveal (expert review page, case review): everything drawn, nothing animates. */
.still .revealTrace, .still .revealLabel, .still .revealArrowText, .still .settle, .still .revealRing, .still .revealHalo { animation: none; }
.still .revealOutline, .still .revealArrow, .still .revealArrowHead { animation: none; stroke-dashoffset: 0; stroke-dasharray: none; }
.still .revealOutline { fill-opacity: 0.07; }
/* Anatomy (key A, after submit): a near-black line on a 1 px light casing reads on dark lung and bright mediastinum. */
.zone, .zoneCasing { fill: none; stroke-linejoin: round; stroke-linecap: round; }
.zoneCasing { stroke: rgba(236, 241, 245, 0.78); pointer-events: none; }
.zoneCasingOn { stroke: #fff; }
.zone { fill: transparent; stroke: #07090b; pointer-events: all; }
.zoneOn { fill: rgba(236, 241, 245, 0.14); }
.zoneName { color: #e6ebef; }
/* Before the first mark: one quiet line in the strip. */
.nudge { display: inline-flex; gap: 14px; color: #c9d1d8; }
.nudge span + span::before { content: '·'; margin-right: 14px; color: #6b7680; }
.kbdTool {
display: inline-block;
margin-left: 6px;
padding: 0 5px;
border: 1px solid #4a535c;
border-radius: 3px;
font: inherit;
font-size: 12px;
line-height: 16px;
color: #c9d1d8;
}
.toolOn .kbdTool { border-color: #9aa5af; color: #333; }
/* On-film legend: what the amber trace and the anatomy lines mean. Small, bottom-left, never below 13 px. */
.legend {
position: absolute;
left: 10px;
bottom: 10px;
z-index: 2;
display: flex;
flex-direction: column;
gap: 6px;
max-width: min(330px, 46%);
cursor: default;
}
.legendChip {
display: flex;
align-items: flex-start;
gap: 8px;
padding: 6px 10px;
border-radius: var(--radius);
background: rgba(9, 11, 13, 0.86);
border: 1px solid rgba(140, 153, 166, 0.35);
color: #e6ebef;
font-size: 13px;
line-height: 1.4;
user-select: text;
}
:root[data-projector='1'] .legendChip { font-size: 16px; }
.legendSwatch {
flex-shrink: 0;
width: 14px;
height: 14px;
margin-top: 2px;
border-radius: 50%;
background: radial-gradient(circle, #ffe5a6 0%, var(--grease-amber) 45%, rgba(240, 169, 46, 0) 100%);
}
.legendLink { background: none; border: none; padding: 0; color: #fff; text-decoration: underline; cursor: pointer; font-size: inherit; }
.legendLine { display: block; margin-top: 3px; }
.legendRing { display: inline-block; width: 12px; height: 12px; margin-right: 6px; border-radius: 50%; border: 1.5px dashed var(--grease-amber); vertical-align: -2px; }
.legendKey { display: inline-block; width: 22px; height: 8px; margin-right: 5px; vertical-align: 0; }
.legendKey + .legendKey, .legendGap { margin-left: 10px; }
/* ---- Volumes (CT / MR): the same room, the volume inside the film area. ---- */
.measuring { cursor: crosshair; }
.windowing { cursor: ns-resize; }
.markGhost { opacity: 0.45; }
/* "Not in the reference": a dotted grey ring, neither cyan (truth) nor amber (learner). */
.unmatchedRing { fill: none; stroke: #b8c2cc; stroke-opacity: 0.9; stroke-linecap: round; }
.caliperCasing { stroke: rgba(0, 0, 0, 0.6); stroke-linecap: round; }
.caliperLine { stroke: var(--grease-amber); stroke-linecap: round; }
.caliperEnd { fill: var(--film-black); stroke: var(--grease-amber); }
.caliperText {
fill: var(--grease-amber);
font-weight: 700;
paint-order: stroke;
stroke: rgba(0, 0, 0, 0.85);
stroke-linejoin: round;
font-variant-numeric: tabular-nums;
}
.stripMeasure { margin-left: 8px; padding: 1px 8px; border-radius: 999px; background: var(--grease-amber); color: #1d1300; font-weight: 700; font-variant-numeric: tabular-nums; }
.wlReadout {
position: absolute;
right: 10px;
top: 8px;
padding: 2px 8px;
border-radius: 4px;
background: rgba(9, 11, 13, 0.72);
color: #c9d1d8;
font-size: var(--fs-1);
font-variant-numeric: tabular-nums;
pointer-events: none;
z-index: 2;
}
/* Component tints (brain): three cyan opacities under the outline. */
.component { fill: var(--lightbox-cyan); stroke: none; }
.compKey { display: inline-flex; gap: 10px; margin-left: 12px; color: #c9d1d8; }
.compKey i { display: inline-block; width: 12px; height: 12px; border-radius: 2px; background: var(--lightbox-cyan); vertical-align: -2px; }
/* Anatomy on a slice: organ zones tinted in graticule grey at 30 %. */
.zoneTint { fill: var(--graticule); fill-opacity: 0.3; stroke: var(--graticule); stroke-opacity: 0.8; pointer-events: all; }
.zoneTintOn { fill-opacity: 0.45; }
.legendTint { display: inline-block; width: 14px; height: 10px; border-radius: 2px; background: var(--graticule); opacity: 0.5; margin-right: 6px; vertical-align: -1px; }
/* The 2×2 grid. */
.grid {
position: absolute;
inset: 0;
display: grid;
grid-template-columns: 1fr 1fr;
grid-template-rows: 1fr 1fr;
gap: 2px;
background: #000;
}
.pane { position: relative; overflow: hidden; background: var(--pacs-surround); cursor: default; }
.pane:hover { box-shadow: inset 0 0 0 1px var(--graticule); }
.paneTag {
position: absolute;
left: 8px;
top: 6px;
padding: 1px 7px;
border-radius: 4px;
background: rgba(9, 11, 13, 0.72);
color: #e6ebef;
font-size: var(--fs-1);
pointer-events: none;
}
.paneInfo { padding: 14px 16px; color: #c9d1d8; font-size: var(--fs-1); overflow: auto; background: #15181a; }
.infoList { margin: 0 0 10px; display: grid; grid-template-columns: auto 1fr; gap: 3px 12px; }
.infoList div { display: contents; }
.infoList dt { color: #8c99a6; }
.infoList dd { margin: 0; color: #e6ebef; font-variant-numeric: tabular-nums; }
.infoBadge { display: inline-block; margin: 2px 0 10px; }
.infoKey { display: flex; flex-direction: column; gap: 6px; margin: 4px 0 10px; }
.infoHint { margin: 0; color: #8c99a6; }
/* Slice controls. */
.sliceGroup { display: inline-flex; align-items: center; gap: 10px; }
.sliceSlider { width: 180px !important; }
.select {
background: #1c2024;
color: #e6ebef;
border: 1px solid #3a4148;
border-radius: 4px;
padding: 3px 6px;
font: inherit;
font-size: var(--fs-1);
}
/* The slice dwell bar: one cell per slice, cyan where the finding lives, amber height = time there. */
.dwell { display: inline-flex; align-items: center; gap: 8px; }
.dwellCells { display: inline-flex; align-items: flex-end; gap: 1px; height: 22px; width: 180px; padding: 1px; background: #0c0e10; border-radius: 3px; }
.dwellCell {
position: relative;
flex: 1 1 0;
min-width: 2px;
height: 100%;
padding: 0;
border: none;
border-radius: 1px;
background: #22272c;
cursor: pointer;
overflow: hidden;
}
.dwellFinding { background: rgba(94, 234, 255, 0.35); }
.dwellMissed { box-shadow: inset 0 0 0 1px var(--grease-amber); background: rgba(94, 234, 255, 0.18); }
.dwellCurrent { outline: 1px solid #e6ebef; outline-offset: -1px; }
.dwellFill { position: absolute; left: 0; right: 0; bottom: 0; background: var(--grease-amber); opacity: 0.9; }
.dwellNote { color: #c9d1d8; max-width: 260px; white-space: normal; line-height: 1.2; }
/* ---- Round 5: signs (cyan cues after submit), the Draw tool and outlined marks, the segmented tool strip. ---- */
.sign { pointer-events: visiblePainted; cursor: help; outline: none; }
/* With the anatomy on, the zones own the pointer (their names show on hover); the signs stay visible, not hoverable. */
.stage[data-anatomy='1'] .sign { pointer-events: none; }
.sign:focus-visible .signText { text-decoration: underline; }
.signCasing { fill: none; stroke: rgba(0, 0, 0, 0.6); stroke-linecap: round; stroke-linejoin: round; }
.signLine { fill: none; stroke: var(--lightbox-cyan); stroke-linecap: round; stroke-linejoin: round; }
.signBand { fill: var(--lightbox-cyan); fill-opacity: 0.25; stroke: var(--lightbox-cyan); stroke-opacity: 0.5; }
.signText { fill: var(--lightbox-cyan); font-weight: 700; }
.signTip { fill: #e6ebef; font-weight: 400; }
.signLeader { stroke: var(--lightbox-cyan); stroke-opacity: 0.8; stroke-linecap: round; }
.signTipBox { pointer-events: none; }
.signTipBox .pill { stroke: var(--lightbox-cyan); stroke-opacity: 0.6; stroke-width: 1px; }
.revealSign { animation: fade 240ms ease-out 700ms both; }
/* focusSign(): two beats on the line, then it rests. */
.signPulse .signLine, .signPulse .signBand { animation: signPulse 1500ms ease-in-out both; }
@keyframes signPulse {
0% { stroke-width: 2px; stroke-opacity: 1; }
25% { stroke-opacity: 0.25; }
50% { stroke-opacity: 1; }
75% { stroke-opacity: 0.25; }
100% { stroke-opacity: 1; }
}
.signPulse .pill { stroke: var(--lightbox-cyan); stroke-width: 1.5px; }
@media (prefers-reduced-motion: reduce) {
.revealSign { animation: none; }
.signPulse .signLine, .signPulse .signBand { animation: none; }
}
.still .revealSign { animation: none; }
/* Drawn marks: a closed amber path (filled faintly) with the usual tag at its centroid. Unfinished = dashed. */
.outlineMark { fill: var(--grease-amber); fill-opacity: 0.1; stroke: var(--grease-amber); stroke-linejoin: round; cursor: grab; pointer-events: visiblePainted; }
.outlineMarkCasing { fill: none; stroke: rgba(0, 0, 0, 0.55); stroke-linejoin: round; }
.outlineMarkSel { fill-opacity: 0.18; }
/* The stroke being drawn right now. */
.drawing { cursor: crosshair; }
.strokeLive { fill: var(--grease-amber); fill-opacity: 0.08; stroke: var(--grease-amber); stroke-linejoin: round; stroke-linecap: round; }
/* Outline verdict chip ("On target", "Partly on it", "Too broad") beside a drawn mark after the reveal. */
.verdictChip { fill: rgba(9, 11, 13, 0.88); stroke: var(--grease-amber); }
.verdictText { fill: var(--grease-amber); font-weight: 700; }
/* Segmented tools: Point · Draw · Caliper, as one control. */
.segment { display: inline-flex; align-items: stretch; border: 1px solid #3a4046; border-radius: var(--radius); overflow: hidden; }
.segment .tool { border: none; border-radius: 0; }
.segment .tool + .tool { border-left: 1px solid #3a4046; }
.segment .tool:hover { border-color: #3a4046; }
.segment .toolOn + .tool { border-left-color: #e6ebef; }
/* "My search" off: the legend chip stays, as a plain note. */
.legendMuted { color: #c9d1d8; }