Components (new public exports, existing APIs unchanged) - SWPopupPropertyRow: the property window row (layer / color / line style pickers, Figma 26:12250 / 26:12170) for SWPopup content. The SWHeader field dropdowns stay header-only; Popup B and 도면 설정 now use the popup pickers. - SWSelect: native panel select (28px, 1px #948871, radius 4, #F1ECE1, 12px), used by Popup 도면 설정 단위 and Viewer 축척 지정 단위 (replaces the HM UI Select there and the story-only .sw-viewer-story-select CSS). - SWSlider: appearance "panel" (default, the gauge the popup used) or "property" (the property window gauge), same value / events. Shares the property gauge CSS; SWViewerSlider renders SWSlider panel with viewer tokens. Footer - --hm-sw-footer-gra-border-orange (Figma gra-border-orange; the aux selected border token now references it): Model selected / hover, Layout hover and Layout + hover surfaces; 보조기능 / 명령어 전체보기 hover lights both lines and an orange ring; category + hover in #FF5C00 (menu-add-hover.svg). - Model / Layout text stays the Default text (#161410, 12px, 400, no outline) on hover and on the orange surface: only the surface changes. - bg_vacant covers the slot row only: the open pocket of a category tab no longer splits where it crosses the last command (e.g. 수정 with one command). Viewer - Panel title art keeps 308px (max-width: none against host img resets), so panels under 312px (250 x auto, 300px) paint the title from the left edge. Storybook - SW/Footer: 기본 Footer (sw-footer--default) and States (sw-footer--states) removed; full-footer keeps the live composition only, responsive keeps the widths (reference / Figma image sections removed, image files kept); the aux Figma comparison moved to the verification Story figma-variants. - SW/Popup: unit SWSelect, SWSlider A / B section, popup pickers, Popup B state.
489 lines
25 KiB
CSS
489 lines
25 KiB
CSS
/* @hm-design/sw — SW viewer mode (reference: DWG/DXF viewer top menu and floating panels, measured 2026-10-19).
|
|
Viewer-only tokens. The three header surfaces reuse the user-confirmed SW tokens of sw.css
|
|
(--hm-sw-header-document-* / object-* / property-*). Never touches global selectors or the SWHeader.
|
|
Declared on the outermost SW scope only, like sw.css: nested viewer menus / panels inherit the tokens. */
|
|
|
|
:is(.hm-sw-header, .hm-sw-theme):not(:where(.hm-sw-header, .hm-sw-theme) *) {
|
|
/* Header */
|
|
--hm-sw-viewer-height: 52px;
|
|
--hm-sw-viewer-background: linear-gradient(180deg, #266651 0%, #123328 45%, #0a221d 100%);
|
|
--hm-sw-viewer-border-color: #071e18;
|
|
--hm-sw-viewer-brand-width: 72px;
|
|
/* No logo: no text or icon is drawn; the cap keeps only its slanted edge (no wide empty space). */
|
|
--hm-sw-viewer-brand-empty-width: 24px;
|
|
--hm-sw-viewer-brand-top: #123328;
|
|
--hm-sw-viewer-brand-middle: #205241;
|
|
--hm-sw-viewer-brand-bottom: #071e18;
|
|
--hm-sw-viewer-text: #fff;
|
|
--hm-sw-viewer-muted: #bddfd4;
|
|
--hm-sw-viewer-accent: #ffc600;
|
|
--hm-sw-viewer-hover: #266651;
|
|
--hm-sw-viewer-gap: 4px;
|
|
--hm-sw-viewer-radius: 4px;
|
|
--hm-sw-viewer-control-height: 40px;
|
|
--hm-sw-viewer-button-height: 34px;
|
|
--hm-sw-viewer-font-size: 14px;
|
|
--hm-sw-viewer-label-size: 11px;
|
|
--hm-sw-viewer-icon-size: 16px;
|
|
--hm-sw-viewer-disabled-opacity: 0.6;
|
|
--hm-sw-viewer-switch-off: #0a221d;
|
|
--hm-sw-viewer-switch-bevel: inset 0 1px 0 rgba(255, 255, 255, 0.1), inset 0 -1px 1px rgba(0, 0, 0, 0.25);
|
|
/* Icon stroke: the SWHeader icon assets (print / K guide / layer icons) are a fill + a 1px black OUTSIDE stroke
|
|
(Figma mask "outside" path). SWViewerIcon draws it as SVG stroke on a copy behind the icon (see SWViewerIcon). */
|
|
--hm-sw-viewer-icon-outline-color: var(--hm-sw-header-text-outline-color);
|
|
--hm-sw-viewer-icon-outline-width: 1px;
|
|
|
|
/* Dropdown (light) and More (beige) */
|
|
--hm-sw-viewer-menu-background: #fff;
|
|
--hm-sw-viewer-menu-border-color: #dedbd2;
|
|
--hm-sw-viewer-menu-text: #0a221d;
|
|
--hm-sw-viewer-menu-muted: #6e6759;
|
|
--hm-sw-viewer-menu-highlight: rgba(189, 223, 212, 0.45);
|
|
--hm-sw-viewer-menu-highlight-text: #123328;
|
|
--hm-sw-viewer-menu-shadow: 0 0 12px rgba(0, 0, 0, 0.2);
|
|
--hm-sw-viewer-menu-item-height: 36px;
|
|
--hm-sw-viewer-more-background: #f5f0e5;
|
|
--hm-sw-viewer-more-border-color: #897445;
|
|
|
|
/* Panel: the frame is SWPopup (title bar, title, close, border, radius, shadow). Content tokens map to the
|
|
SW property window tokens so viewer content sits on the same surface as every SW popup. */
|
|
--hm-sw-viewer-panel-background: var(--hm-sw-property-surface);
|
|
--hm-sw-viewer-panel-field-background: var(--hm-sw-property-content);
|
|
--hm-sw-viewer-panel-inner-border: var(--hm-sw-property-inner-border);
|
|
--hm-sw-viewer-panel-text: var(--hm-sw-property-label);
|
|
--hm-sw-viewer-panel-heading: #3e3523;
|
|
--hm-sw-viewer-panel-label: #6e6759;
|
|
--hm-sw-viewer-panel-primary: #123328;
|
|
--hm-sw-viewer-panel-switch-off: var(--hm-sw-property-inner-border);
|
|
--hm-sw-viewer-panel-switch-on: #266651;
|
|
--hm-sw-viewer-panel-badge-background: var(--hm-sw-property-table);
|
|
--hm-sw-viewer-panel-overlay: rgba(0, 0, 0, 0.1);
|
|
--hm-sw-viewer-panel-spacing: 12px;
|
|
}
|
|
|
|
.hm-sw-viewer-sr-only { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
|
|
|
|
/* ---------- Header ---------- */
|
|
.hm-sw-viewer-header {
|
|
container: hm-sw-viewer / inline-size;
|
|
position: relative;
|
|
box-sizing: border-box;
|
|
display: flex;
|
|
align-items: flex-start;
|
|
gap: 2px;
|
|
width: 100%;
|
|
min-width: 0;
|
|
height: var(--hm-sw-viewer-height);
|
|
border: 1px solid var(--hm-sw-viewer-border-color);
|
|
background: var(--hm-sw-viewer-background);
|
|
color: var(--hm-sw-viewer-text);
|
|
font-size: var(--hm-sw-viewer-font-size);
|
|
font-weight: 500;
|
|
line-height: 20px;
|
|
}
|
|
|
|
.hm-sw-viewer-header__brand {
|
|
position: relative;
|
|
z-index: 2;
|
|
display: flex;
|
|
align-items: center;
|
|
flex: 0 0 auto;
|
|
width: var(--hm-sw-viewer-brand-empty-width);
|
|
height: calc(var(--hm-sw-viewer-height) - 2px);
|
|
margin-right: -2px;
|
|
font-weight: 700;
|
|
}
|
|
/* With a logo: the reference 72px cap (logo at 24px), wider only for a wider logo. Without: the slanted edge only. */
|
|
.hm-sw-viewer-header__brand[data-logo] { width: auto; min-width: var(--hm-sw-viewer-brand-width); padding: 0 25px 0 24px; }
|
|
button.hm-sw-viewer-header__brand { text-align: left; }
|
|
.hm-sw-viewer-header__brand-shape { position: absolute; inset: 0 auto 0 0; width: calc(100% + 16px); height: 100%; pointer-events: none; }
|
|
.hm-sw-viewer-header__brand-mark { position: relative; display: inline-flex; align-items: center; }
|
|
.hm-sw-viewer-header__brand-mark > :is(img, svg) { display: block; max-height: 24px; width: auto; }
|
|
|
|
.hm-sw-viewer-header__document {
|
|
display: flex;
|
|
align-items: center;
|
|
flex: 0 1 clamp(140px, 25cqw, 360px);
|
|
width: clamp(220px, 25cqw, 360px);
|
|
min-width: 56px;
|
|
height: calc(var(--hm-sw-viewer-height) - 2px);
|
|
padding: 0 16px 0 24px;
|
|
border: 1px solid var(--hm-sw-header-document-border-color);
|
|
border-left: 0;
|
|
background: var(--hm-sw-header-document-background);
|
|
}
|
|
.hm-sw-viewer-header__document-name { min-width: 0; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }
|
|
|
|
.hm-sw-viewer-header__object {
|
|
display: flex;
|
|
align-items: center;
|
|
flex: 1 0 auto;
|
|
min-width: 0;
|
|
height: calc(var(--hm-sw-viewer-height) - 2px);
|
|
gap: var(--hm-sw-viewer-gap);
|
|
padding-inline: var(--hm-sw-viewer-gap);
|
|
border: 1px solid var(--hm-sw-header-object-border-color);
|
|
border-radius: var(--hm-sw-header-object-radius);
|
|
background: var(--hm-sw-header-object-background);
|
|
}
|
|
|
|
.hm-sw-viewer-header__group {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: var(--hm-sw-viewer-gap);
|
|
min-height: var(--hm-sw-viewer-control-height);
|
|
padding-inline: var(--hm-sw-viewer-gap);
|
|
}
|
|
.hm-sw-viewer-header__group[data-surface="field"] {
|
|
border: 1px solid var(--hm-sw-header-property-border-color);
|
|
border-radius: var(--hm-sw-header-property-radius);
|
|
background: var(--hm-sw-header-property-background);
|
|
box-shadow: var(--hm-sw-header-property-shadow);
|
|
}
|
|
.hm-sw-viewer-header__actions {
|
|
display: flex;
|
|
align-items: center;
|
|
align-self: stretch;
|
|
gap: var(--hm-sw-viewer-gap);
|
|
margin-left: auto;
|
|
padding-left: 6px;
|
|
}
|
|
|
|
/* Buttons, menu buttons and toggles: transparent, #266651 hover, #FFC600 pressed / open / on (no selected box). */
|
|
.hm-sw-viewer-header .hm-sw-viewer-header__button {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
flex-shrink: 0;
|
|
gap: 8px;
|
|
height: var(--hm-sw-viewer-button-height);
|
|
padding: 6px 14px;
|
|
border: 1px solid transparent;
|
|
border-radius: var(--hm-sw-viewer-radius);
|
|
color: var(--hm-sw-viewer-text);
|
|
font-weight: 500;
|
|
line-height: 20px;
|
|
white-space: nowrap;
|
|
}
|
|
.hm-sw-viewer-header .hm-sw-viewer-header__button[data-kind="toggle"] { height: var(--hm-sw-viewer-control-height); padding: 0 8px; }
|
|
.hm-sw-viewer-header .hm-sw-viewer-header__button[data-icon-only] { min-width: var(--hm-sw-viewer-button-height); padding: 0 8px; }
|
|
/* Always-icon buttons (info, More): the reference 32 x 40 icon button. */
|
|
.hm-sw-viewer-header .hm-sw-viewer-header__button[data-icon-only="always"] { min-width: 32px; width: 32px; height: var(--hm-sw-viewer-control-height); padding: 0 8px; }
|
|
.hm-sw-viewer-header .hm-sw-viewer-header__button:hover:not(:disabled) { background: var(--hm-sw-viewer-hover); }
|
|
.hm-sw-viewer-header .hm-sw-viewer-header__button:active:not(:disabled),
|
|
.hm-sw-viewer-header .hm-sw-viewer-header__button:is([data-state="open"], [data-state="on"]) { color: var(--hm-sw-viewer-accent); }
|
|
.hm-sw-viewer-header .hm-sw-viewer-header__button:is([data-state="open"], [data-state="on"]):not(:hover) { background: transparent; }
|
|
.hm-sw-viewer-header :is(.hm-sw-viewer-header__button, .hm-sw-viewer-header__tab):disabled { opacity: var(--hm-sw-viewer-disabled-opacity); cursor: not-allowed; }
|
|
.hm-sw-viewer-header__icon, .hm-sw-viewer-header__chevron { display: inline-flex; width: var(--hm-sw-viewer-icon-size); height: var(--hm-sw-viewer-icon-size); }
|
|
.hm-sw-viewer-header__icon > svg, .hm-sw-viewer-header__chevron > svg { width: 100%; height: 100%; }
|
|
|
|
/* SWViewerIcon: the outline copy (black SVG stroke) right behind the untouched icon. */
|
|
.hm-sw-viewer-icon { position: relative; display: inline-flex; width: 100%; height: 100%; }
|
|
.hm-sw-viewer-icon__outline, .hm-sw-viewer-icon__glyph { display: inline-flex; width: 100%; height: 100%; }
|
|
.hm-sw-viewer-icon__outline { position: absolute; inset: 0; overflow: visible; }
|
|
.hm-sw-viewer-icon__glyph { position: relative; }
|
|
.hm-sw-viewer-icon svg { width: 100%; height: 100%; overflow: visible; }
|
|
|
|
/* Tabs (Model / Layout): 40px triggers with an 11px count; the active one turns #FFC600. */
|
|
.hm-sw-viewer-header__tabs { display: flex; align-items: center; gap: var(--hm-sw-viewer-gap); }
|
|
.hm-sw-viewer-header .hm-sw-viewer-header__tab {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
gap: var(--hm-sw-viewer-gap);
|
|
height: var(--hm-sw-viewer-control-height);
|
|
padding: 0 8px;
|
|
border: 1px solid transparent;
|
|
border-radius: var(--hm-sw-viewer-radius);
|
|
color: var(--hm-sw-viewer-text);
|
|
font-weight: 500;
|
|
line-height: 1.4;
|
|
white-space: nowrap;
|
|
}
|
|
.hm-sw-viewer-header .hm-sw-viewer-header__tab:hover:not(:disabled) { background: var(--hm-sw-viewer-hover); }
|
|
.hm-sw-viewer-header .hm-sw-viewer-header__tab[data-state="active"] { color: var(--hm-sw-viewer-accent); }
|
|
.hm-sw-viewer-header__count { font-size: var(--hm-sw-viewer-label-size); font-weight: 400; font-variant-numeric: tabular-nums; }
|
|
|
|
/* Switch fields (2.5D, 어두운 배경): 11px muted caption above the switch. */
|
|
.hm-sw-viewer-header__switch-field {
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
justify-content: center;
|
|
gap: var(--hm-sw-viewer-gap);
|
|
min-height: var(--hm-sw-viewer-control-height);
|
|
padding-inline: 8px;
|
|
}
|
|
.hm-sw-viewer-header__switch-label { color: var(--hm-sw-viewer-muted); font-size: var(--hm-sw-viewer-label-size); font-weight: 400; line-height: 1; white-space: nowrap; }
|
|
|
|
.hm-sw-viewer-header :is(.hm-sw-viewer-header__button, .hm-sw-viewer-header__tab, .hm-sw-viewer-header__brand, .hm-sw-viewer-switch):focus-visible {
|
|
outline: 2px solid var(--hm-sw-viewer-accent);
|
|
outline-offset: 2px;
|
|
}
|
|
|
|
/* Text and icon stroke (2026-10-19 request): the SWHeader black outline on the viewer header, same tokens and
|
|
method — an outside outline of the glyph / icon shape, never a box border.
|
|
Text: 14px = --hm-sw-header-text-outline (1.3px black), 11px captions / counts / status = --hm-sw-header-label-outline
|
|
(1px black), as SWHeader's 12px labels. Icons: SWViewerIcon (SVG stroke, see the token). Fill color, size,
|
|
weight and spacing are unchanged; hover / active / open change only the fill, disabled fades the whole button
|
|
(opacity) like SWHeader. Dropdown faces (light / beige) and panels get no outline, like SWHeader's More menu. */
|
|
.hm-sw-viewer-header :is(
|
|
.hm-sw-viewer-header__brand-mark, .hm-sw-viewer-header__document-name, .hm-sw-viewer-header__label, .hm-sw-viewer-header__tab
|
|
) {
|
|
text-shadow: var(--hm-sw-header-text-outline);
|
|
}
|
|
.hm-sw-viewer-header :is(.hm-sw-viewer-header__count, .hm-sw-viewer-header__switch-label, .hm-sw-viewer-status__label) {
|
|
text-shadow: var(--hm-sw-header-label-outline);
|
|
}
|
|
/* Clipped (ellipsis) file name: the outline may paint 2px outside the box instead of being cut. */
|
|
.hm-sw-viewer-header .hm-sw-viewer-header__document-name {
|
|
overflow: clip;
|
|
overflow-clip-margin: var(--hm-sw-header-text-outline-room);
|
|
}
|
|
|
|
/* Status */
|
|
.hm-sw-viewer-status {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: var(--hm-sw-viewer-gap);
|
|
padding-inline: 8px;
|
|
color: var(--hm-sw-viewer-muted);
|
|
font-size: var(--hm-sw-viewer-label-size);
|
|
font-weight: 400;
|
|
white-space: nowrap;
|
|
}
|
|
.hm-sw-viewer-status__icon { display: inline-flex; width: var(--hm-sw-viewer-icon-size); height: var(--hm-sw-viewer-icon-size); }
|
|
.hm-sw-viewer-status[data-state="error"] { color: var(--hm-sw-viewer-accent); }
|
|
.hm-sw-viewer-status__spin { animation: hm-sw-viewer-spin 1s linear infinite; }
|
|
@keyframes hm-sw-viewer-spin { to { transform: rotate(360deg); } }
|
|
@media (prefers-reduced-motion: reduce) { .hm-sw-viewer-status__spin { animation: none; } }
|
|
|
|
/* Narrow header (reference breakpoints, measured on the header itself). */
|
|
@container hm-sw-viewer (max-width: 1179.98px) {
|
|
.hm-sw-viewer-header__object { gap: 2px; padding-inline: 2px; }
|
|
.hm-sw-viewer-header__group { gap: 2px; padding-inline: 2px; }
|
|
.hm-sw-viewer-header__actions { padding-left: 2px; gap: 2px; }
|
|
.hm-sw-viewer-status { padding-inline: 2px; }
|
|
}
|
|
@container hm-sw-viewer (max-width: 559.98px) {
|
|
.hm-sw-viewer-header__document { padding-right: 8px; }
|
|
.hm-sw-viewer-status__label { display: none; }
|
|
}
|
|
|
|
/* ---------- Switch (header / panel faces) ---------- */
|
|
.hm-sw-theme .hm-sw-viewer-switch {
|
|
position: relative;
|
|
display: inline-flex;
|
|
align-items: center;
|
|
flex-shrink: 0;
|
|
width: 36px;
|
|
height: 20px;
|
|
padding: 2px;
|
|
border-radius: 9999px;
|
|
background: var(--hm-sw-viewer-switch-off);
|
|
box-shadow: var(--hm-sw-viewer-switch-bevel);
|
|
transition: background-color 0.15s;
|
|
}
|
|
.hm-sw-viewer-switch__thumb { display: block; width: 16px; height: 16px; border-radius: 9999px; background: var(--hm-sw-viewer-text); transition: transform 0.15s; }
|
|
.hm-sw-viewer-switch[data-state="checked"] { background: var(--hm-sw-viewer-accent); }
|
|
.hm-sw-viewer-switch[data-state="checked"] .hm-sw-viewer-switch__thumb { transform: translateX(16px); background: var(--hm-sw-viewer-switch-off); }
|
|
.hm-sw-theme .hm-sw-viewer-switch:disabled { opacity: var(--hm-sw-viewer-disabled-opacity); cursor: not-allowed; }
|
|
.hm-sw-viewer-panel .hm-sw-viewer-switch { background: var(--hm-sw-viewer-panel-switch-off); box-shadow: none; }
|
|
.hm-sw-viewer-panel .hm-sw-viewer-switch .hm-sw-viewer-switch__thumb { background: #fff; }
|
|
.hm-sw-viewer-panel .hm-sw-viewer-switch[data-state="checked"] { background: var(--hm-sw-viewer-panel-switch-on); }
|
|
@media (prefers-reduced-motion: reduce) { .hm-sw-viewer-switch, .hm-sw-viewer-switch__thumb { transition: none; } }
|
|
|
|
/* ---------- Dropdown ---------- */
|
|
/* The menu renders next to its trigger inside the header flex rows: the wrapper must not become a flex item, or the
|
|
row gains one gap while a menu is open (file name well shrinks, trigger shifts). The fixed list is out of flow. */
|
|
.hm-sw-viewer-menu-root { display: contents; }
|
|
.hm-sw-viewer-menu {
|
|
position: fixed;
|
|
z-index: 60;
|
|
display: flex;
|
|
flex-direction: column;
|
|
min-width: 160px;
|
|
max-width: calc(100vw - 8px);
|
|
max-height: min(640px, calc(100dvh - 8px));
|
|
overflow-y: auto;
|
|
padding: 4px;
|
|
border: 1px solid var(--hm-sw-viewer-menu-border-color);
|
|
border-radius: var(--hm-sw-viewer-radius);
|
|
background: var(--hm-sw-viewer-menu-background);
|
|
box-shadow: var(--hm-sw-viewer-menu-shadow);
|
|
color: var(--hm-sw-viewer-menu-text);
|
|
font-size: 14px;
|
|
font-weight: 400;
|
|
line-height: 20px;
|
|
outline: none;
|
|
}
|
|
.hm-sw-viewer-menu[data-surface="beige"] { background: var(--hm-sw-viewer-more-background); border-color: var(--hm-sw-viewer-more-border-color); }
|
|
.hm-sw-viewer-menu .hm-sw-viewer-menu__item {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 8px;
|
|
width: 100%;
|
|
min-height: var(--hm-sw-viewer-menu-item-height);
|
|
padding: 0 12px;
|
|
border-radius: 2px;
|
|
color: inherit;
|
|
text-align: left;
|
|
white-space: nowrap;
|
|
outline: none;
|
|
}
|
|
.hm-sw-viewer-menu .hm-sw-viewer-menu__item:is(:focus, :hover, [data-state="open"]):not([aria-disabled]) { background: var(--hm-sw-viewer-menu-highlight); color: var(--hm-sw-viewer-menu-highlight-text); }
|
|
.hm-sw-viewer-menu .hm-sw-viewer-menu__item[aria-disabled] { opacity: 0.5; cursor: not-allowed; }
|
|
.hm-sw-viewer-menu .hm-sw-viewer-menu__item:focus-visible { outline: none; }
|
|
.hm-sw-viewer-menu__icon { display: inline-flex; align-items: center; justify-content: center; flex: 0 0 16px; width: 16px; height: 16px; }
|
|
.hm-sw-viewer-menu__icon:empty { display: none; }
|
|
.hm-sw-viewer-menu__item[role="menuitemcheckbox"] .hm-sw-viewer-menu__icon,
|
|
.hm-sw-viewer-menu__item[role="menuitemradio"] .hm-sw-viewer-menu__icon { display: inline-flex; }
|
|
.hm-sw-viewer-menu__icon > svg { width: 16px; height: 16px; }
|
|
.hm-sw-viewer-menu__dot { width: 8px; height: 8px; border-radius: 9999px; background: currentColor; }
|
|
.hm-sw-viewer-menu__text { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; }
|
|
.hm-sw-viewer-menu__shortcut { margin-left: auto; color: var(--hm-sw-viewer-menu-muted); font-size: 12px; letter-spacing: 0.05em; }
|
|
.hm-sw-viewer-menu__chevron { display: inline-flex; margin-left: auto; color: var(--hm-sw-viewer-menu-muted); }
|
|
.hm-sw-viewer-menu__label { padding: 6px 12px; color: var(--hm-sw-viewer-menu-muted); font-size: 12px; font-weight: 500; line-height: 18px; }
|
|
.hm-sw-viewer-menu__separator { flex: 0 0 1px; height: 1px; margin: 4px -4px; background: var(--hm-sw-viewer-menu-border-color); }
|
|
.hm-sw-viewer-menu[data-surface="beige"] .hm-sw-viewer-menu__separator { background: var(--hm-sw-viewer-panel-inner-border); }
|
|
|
|
/* ---------- Panel (SWPopup frame + viewer window behavior) ---------- */
|
|
.hm-sw-viewer-panel-backdrop { inset: 0; background: var(--hm-sw-viewer-panel-overlay); }
|
|
.hm-sw-viewer-panel[data-collapsed] .hm-sw-property__body { display: none; }
|
|
.hm-sw-viewer-panel[data-draggable] .hm-sw-property__titlebar { cursor: grab; touch-action: none; user-select: none; }
|
|
.hm-sw-viewer-panel[data-dragging] .hm-sw-property__titlebar { cursor: grabbing; }
|
|
/* Any width: the Figma title art keeps its 308px curve at the close button (right-aligned; at 314px this is exactly
|
|
the SWPopup position), and a stretched copy of the same art fills the flat part on the left of wider panels.
|
|
The right one hides its own left 20px (left edge + corner) and the left copy ends exactly there: no seam, no
|
|
doubled shadow. */
|
|
/* max-width: none: a host img reset (e.g. Tailwind preflight max-width: 100%) shrank the art in panels under 312px,
|
|
so its clipped left 20px left the start of the title bar unpainted (2026-10-20, 250px minimum width). */
|
|
.hm-sw-viewer-panel .hm-sw-property__title-art { left: auto; right: 4px; max-width: none; clip-path: inset(-4px -4px -4px 20px); }
|
|
.hm-sw-viewer-panel .hm-sw-property__titlebar::before {
|
|
content: "";
|
|
position: absolute;
|
|
z-index: 1;
|
|
left: 0;
|
|
top: -2px;
|
|
width: max(0px, calc(100% - 292px));
|
|
height: 38px;
|
|
background: url("../assets/property-title-single.svg") left top / calc(100% + 288px) 38px no-repeat;
|
|
transform: scaleY(-1);
|
|
pointer-events: none;
|
|
}
|
|
.hm-sw-viewer-panel__actions { position: relative; z-index: 2; display: flex; flex-shrink: 0; align-items: center; height: 30px; }
|
|
/* Title-bar buttons: SW text-only look (no face), #FFC600 on hover like the SW title-bar controls. */
|
|
.hm-sw-viewer-panel :is(.hm-sw-viewer-panel__icon-button, .hm-sw-viewer-button[data-variant="ghost"]) {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
width: 26px;
|
|
height: 26px;
|
|
padding: 0;
|
|
border: 0;
|
|
border-radius: 0;
|
|
background: transparent;
|
|
color: var(--hm-sw-viewer-muted);
|
|
}
|
|
.hm-sw-viewer-panel :is(.hm-sw-viewer-panel__icon-button, .hm-sw-viewer-button[data-variant="ghost"]):hover:not(:disabled) { background: transparent; color: var(--hm-sw-header-selected-color); }
|
|
.hm-sw-viewer-panel :is(.hm-sw-viewer-panel__icon-button, .hm-sw-viewer-button[data-variant="ghost"]):focus-visible { outline: 2px solid var(--hm-sw-header-selected-color); outline-offset: -2px; }
|
|
.hm-sw-viewer-panel :is(.hm-sw-viewer-panel__icon-button, .hm-sw-viewer-button[data-variant="ghost"]) svg { width: 16px; height: 16px; }
|
|
.hm-sw-viewer-panel__footer {
|
|
display: flex;
|
|
flex-shrink: 0;
|
|
justify-content: flex-end;
|
|
gap: 8px;
|
|
padding: 7px;
|
|
border-top: 1px solid var(--hm-sw-viewer-panel-inner-border);
|
|
}
|
|
|
|
/* Panel content */
|
|
.hm-sw-viewer-section { display: flex; flex-direction: column; gap: 12px; }
|
|
.hm-sw-viewer-section[data-surface="card"] {
|
|
padding: var(--hm-sw-viewer-panel-spacing);
|
|
border: 1px solid var(--hm-sw-viewer-panel-inner-border);
|
|
border-radius: var(--hm-sw-viewer-radius);
|
|
background: var(--hm-sw-viewer-panel-field-background);
|
|
box-shadow: inset 0 1px 0 #fff;
|
|
}
|
|
.hm-sw-viewer-section__title { margin: 0; color: var(--hm-sw-viewer-panel-heading); font-size: 12px; font-weight: 700; line-height: 16px; letter-spacing: 0.025em; text-transform: uppercase; }
|
|
.hm-sw-viewer-hint { margin: 0; color: var(--hm-sw-viewer-panel-heading); font-size: 12px; line-height: 16px; }
|
|
.hm-sw-viewer-field { display: flex; flex-direction: column; gap: 6px; }
|
|
.hm-sw-viewer-field[data-disabled] { opacity: 0.5; pointer-events: none; }
|
|
.hm-sw-viewer-field__row { display: flex; align-items: center; justify-content: space-between; gap: 8px; min-height: 20px; }
|
|
.hm-sw-viewer-field__label { min-width: 0; color: var(--hm-sw-viewer-panel-label); font-size: 14px; font-weight: 500; line-height: 20px; }
|
|
.hm-sw-viewer-field__control { display: flex; align-items: center; gap: 4px; flex-shrink: 0; }
|
|
.hm-sw-viewer-field__unit { color: var(--hm-sw-viewer-panel-label); font-size: 12px; }
|
|
|
|
.hm-sw-theme .hm-sw-viewer-input {
|
|
box-sizing: border-box;
|
|
width: 80px;
|
|
height: 28px;
|
|
padding: 0 10px;
|
|
border: 1px solid var(--hm-sw-viewer-panel-inner-border);
|
|
border-radius: var(--hm-sw-viewer-radius);
|
|
background: var(--hm-sw-viewer-panel-field-background);
|
|
color: var(--hm-sw-viewer-panel-text);
|
|
font: inherit;
|
|
font-size: 12px;
|
|
line-height: 18px;
|
|
}
|
|
.hm-sw-theme .hm-sw-viewer-input:focus-visible { outline: 2px solid var(--hm-sw-viewer-panel-switch-on); outline-offset: -1px; }
|
|
.hm-sw-theme .hm-sw-viewer-input:disabled { opacity: 0.5; }
|
|
|
|
/* SWViewerSlider = SWSlider appearance="panel" (sw.css, 2026-10-20): the shared gauge rules painted with the
|
|
viewer panel tokens, so the viewer look and its theme overrides are unchanged. */
|
|
.hm-sw-viewer-slider {
|
|
--hm-sw-slider-panel-range: var(--hm-sw-viewer-panel-switch-on);
|
|
--hm-sw-slider-panel-track: var(--hm-sw-viewer-panel-background);
|
|
--hm-sw-slider-panel-thumb: #fff;
|
|
}
|
|
/* SWSelect inside viewer panels reads the viewer panel tokens (same values; viewer theme overrides follow). */
|
|
.hm-sw-viewer-panel { --hm-sw-select-border-color: var(--hm-sw-viewer-panel-inner-border); --hm-sw-select-background: var(--hm-sw-viewer-panel-field-background); --hm-sw-select-text: var(--hm-sw-viewer-panel-text); }
|
|
/* Viewer rows dim a disabled field as a whole (SWViewerField 50%); the slider keeps its own opacity as before. */
|
|
.hm-sw-theme .hm-sw-viewer-slider:disabled { opacity: 1; }
|
|
|
|
.hm-sw-theme .hm-sw-viewer-button {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
gap: 4px;
|
|
height: 24px;
|
|
padding: 0 8px;
|
|
border: 1px solid var(--hm-sw-viewer-panel-primary);
|
|
border-radius: var(--hm-sw-viewer-radius);
|
|
background: #fff;
|
|
color: var(--hm-sw-viewer-panel-primary);
|
|
font-size: 12px;
|
|
font-weight: 500;
|
|
line-height: 16px;
|
|
white-space: nowrap;
|
|
}
|
|
.hm-sw-theme .hm-sw-viewer-button[data-variant="outline"]:hover:not(:disabled) { background: var(--hm-sw-viewer-panel-field-background); }
|
|
.hm-sw-theme .hm-sw-viewer-button[data-variant="primary"] { background: var(--hm-sw-viewer-panel-primary); color: #fff; }
|
|
/* tone="green" (e.g. 전체 켜기 / 전체 끄기): default unchanged. Hover = the primary (확인) button hover, the same token;
|
|
pressed = the primary button face. White text as on the primary button. Back to default / hover after the press. */
|
|
.hm-sw-theme .hm-sw-viewer-button[data-tone="green"]:hover:not(:disabled) { border-color: var(--hm-sw-viewer-hover); background: var(--hm-sw-viewer-hover); color: #fff; }
|
|
.hm-sw-theme .hm-sw-viewer-button[data-tone="green"]:active:not(:disabled) { border-color: var(--hm-sw-viewer-panel-primary); background: var(--hm-sw-viewer-panel-primary); color: #fff; }
|
|
.hm-sw-theme .hm-sw-viewer-button[data-variant="primary"]:hover:not(:disabled) { background: var(--hm-sw-viewer-hover); border-color: var(--hm-sw-viewer-hover); }
|
|
.hm-sw-theme .hm-sw-viewer-button:focus-visible { outline: 2px solid var(--hm-sw-viewer-panel-switch-on); outline-offset: 1px; }
|
|
.hm-sw-theme .hm-sw-viewer-button:disabled { opacity: 0.5; cursor: not-allowed; }
|
|
.hm-sw-viewer-button__icon { display: inline-flex; width: 16px; height: 16px; }
|
|
.hm-sw-viewer-button__icon > svg { width: 100%; height: 100%; }
|
|
|
|
.hm-sw-viewer-badge { display: inline-flex; align-items: center; padding: 2px 8px; border-radius: var(--hm-sw-viewer-radius); background: var(--hm-sw-viewer-panel-badge-background); color: var(--hm-sw-viewer-panel-label); font-size: 12px; font-weight: 500; line-height: 18px; font-variant-numeric: tabular-nums; }
|
|
|
|
/* Corner resize grip (replaces native resize: same corner and glyph idea, works in every browser and with
|
|
pointer capture; the size stays within min / 90% of the bounds / the bounds edge). */
|
|
.hm-sw-viewer-panel__resize {
|
|
position: absolute;
|
|
right: 0;
|
|
bottom: 0;
|
|
z-index: 1;
|
|
width: 14px;
|
|
height: 14px;
|
|
cursor: nwse-resize;
|
|
touch-action: none;
|
|
background:
|
|
linear-gradient(135deg, transparent 0 55%, var(--hm-sw-viewer-panel-inner-border) 55% 62%, transparent 62% 72%, var(--hm-sw-viewer-panel-inner-border) 72% 79%, transparent 79%);
|
|
}
|