diff options
Diffstat (limited to 'bluebey-studio/src/style.css')
| -rw-r--r-- | bluebey-studio/src/style.css | 880 |
1 files changed, 880 insertions, 0 deletions
diff --git a/bluebey-studio/src/style.css b/bluebey-studio/src/style.css new file mode 100644 index 0000000..a147b1f --- /dev/null +++ b/bluebey-studio/src/style.css @@ -0,0 +1,880 @@ +:root { + --accent: #7b53d1; + --accent-soft: #efe8fd; + --accent-2: #b498ff; + --text: #2b2433; + --muted: #6f6682; + --border: #e4dff0; + --card: rgba(255, 255, 255, 0.94); + --radius: 12px; + --panel-width: 344px; +} + +* { box-sizing: border-box; } + +html, body { + margin: 0; + height: 100%; + height: 100vh; + /* `dvh` tracks the space mobile browser chrome leaves; the lines above are + the fallbacks for browsers that do not know it yet. */ + height: 100dvh; + overflow: hidden; +} + +body { + font-family: system-ui, -apple-system, "Segoe UI", "Hiragino Kaku Gothic ProN", "Noto Sans JP", Meiryo, sans-serif; + color: var(--text); + background: radial-gradient(120% 120% at 30% 0%, #f7f5fc 0%, #ece8f4 60%, #e4e0ee 100%); + -webkit-font-smoothing: antialiased; +} + +/* ------------------------------------------------------------------ viewport */ + +/* + * The canvas gets its size from #stage, never from its own width/height + * attributes: a canvas is a replaced element, so `width: auto` would make its + * layout follow those attributes - and since the renderer writes them, that + * becomes a resize feedback loop that leaves the picture blank. + */ +#stage { + position: fixed; + inset: 0; +} + +body:not(.panel-hidden) #stage { + right: var(--panel-width); +} + +#view { + display: block; + width: 100%; + height: 100%; + touch-action: none; + outline: none; +} + +/* ------------------------------------------------------------------- topbar */ + +#topbar { + position: fixed; + top: 14px; + left: 16px; + z-index: 20; + display: flex; + align-items: center; + gap: 14px; + max-width: calc(100vw - var(--panel-width) - 48px); +} + +#topbar h1 { + margin: 0; + font-size: 16px; + font-weight: 700; + letter-spacing: 0.02em; + color: #4b3a72; + text-shadow: 0 1px 0 rgba(255, 255, 255, 0.7); +} + +.topbar-actions { display: flex; flex-wrap: wrap; gap: 6px; } + +#topbar button { + font: inherit; + font-size: 12px; + padding: 6px 11px; + border-radius: 999px; + border: 1px solid rgba(123, 83, 209, 0.22); + background: rgba(255, 255, 255, 0.86); + color: #5a4a7d; + cursor: pointer; + backdrop-filter: blur(6px); + transition: background 0.15s, transform 0.1s; +} + +#topbar button:hover { background: #fff; transform: translateY(-1px); } +#topbar button:active { transform: translateY(0); } +#topbar button[aria-pressed="true"] { background: var(--accent-soft); color: var(--accent); } + +/* Shared by the mouse hint and the touch hint (see #viewport-hint-touch). */ +.viewport-hint { + position: fixed; + left: 18px; + bottom: 14px; + z-index: 10; + margin: 0; + font-size: 11.5px; + color: #8a80a0; + pointer-events: none; +} + +/* Phones get a touch-specific hint instead of this mouse one; swapped in the + small-screen media query at the end of the viewport/panel section below. */ +#viewport-hint-touch { display: none; } + +/* AR (camera) mode's shutter: a camera-app button over the viewport. It is a DOM + layer, so it never appears in the exported PNG. */ +.ar-shutter { + position: absolute; + left: 50%; + bottom: calc(22px + env(safe-area-inset-bottom)); + transform: translateX(-50%); + z-index: 4; + width: 64px; + height: 64px; + padding: 0; + border-radius: 50%; + border: 4px solid #ffffff; + background: rgba(255, 255, 255, 0.35); + box-shadow: 0 2px 12px rgba(0, 0, 0, 0.35); + cursor: pointer; +} +.ar-shutter::after { + content: ""; + position: absolute; + inset: 6px; + border-radius: 50%; + background: #ffffff; +} +.ar-shutter:active::after { background: #d9d2e8; } +.ar-shutter[hidden] { display: none; } + +/* -------------------------------------------------------------------- panel */ + +#panel { + position: fixed; + top: 0; + right: 0; + bottom: 0; + width: var(--panel-width); + padding: 14px 14px 40px; + overflow-y: auto; + overflow-x: hidden; + background: var(--card); + border-left: 1px solid var(--border); + backdrop-filter: blur(10px); + z-index: 30; + scrollbar-width: thin; +} + +#panel::-webkit-scrollbar { width: 9px; } +#panel::-webkit-scrollbar-thumb { background: #d8d1e8; border-radius: 9px; } + +/* The phone sheet's grab handle is a real element (built in the app) so it can + carry a drag; it is hidden everywhere else. */ +.panel-grip { display: none; } + +body.panel-hidden #panel { display: none; } + +body.panel-hidden #topbar { max-width: calc(100vw - 48px); } + +@media (max-width: 780px) { + :root { --panel-width: min(88vw, 344px); } + #topbar { max-width: calc(100vw - 60px); } +} + +/* + * Phones and other short touch screens. The panel becomes a bottom sheet over + * the 3D view instead of a side column: the canvas keeps the full screen behind + * it, so opening the sheet does not resize the render (and the ≡ button, which + * already calls resizeViewport, is all the control needed). + */ +@media (max-width: 768px), (max-height: 500px) and (pointer: coarse) { + /* Full-screen canvas: the sheet floats over it, so its height never feeds + back into the renderer. */ + #stage, + body:not(.panel-hidden) #stage { + inset: 0; + right: 0; + } + + #topbar { + top: calc(8px + env(safe-area-inset-top)); + left: calc(10px + env(safe-area-inset-left)); + right: calc(10px + env(safe-area-inset-right)); + max-width: none; + gap: 8px; + } + + /* Let the title give way first (it can ellipsize); the buttons keep their + labels and stay on one line. */ + #topbar h1 { + font-size: 13px; + white-space: nowrap; + min-width: 0; + overflow: hidden; + text-overflow: ellipsis; + } + + .topbar-actions { + flex: 1; + flex-wrap: nowrap; + justify-content: flex-end; + gap: 6px; + } + + /* Comfortable tap targets (>= 40px) in a row that still fits 360px. */ + #topbar button { + font-size: 11px; + padding: 9px 10px; + min-height: 40px; + } + + #btn-panel { min-width: 44px; } + + #viewport-hint { display: none; } + #viewport-hint-touch { + display: block; + bottom: calc(14px + env(safe-area-inset-bottom)); + } + + #panel { + top: auto; + left: 0; + right: 0; + bottom: 0; + width: auto; + max-height: 65dvh; + padding: 0 14px calc(20px + env(safe-area-inset-bottom)); + border-left: 0; + border-top: 1px solid var(--border); + border-radius: 18px 18px 0 0; + box-shadow: 0 -6px 24px rgba(40, 20, 80, 0.18); + } + + /* The grab handle: sticky at the top of the scroll area, so it stays grabbable + however far the menu is scrolled, and `touch-action: none` so a drag on it + resizes the sheet instead of scrolling it. */ + .panel-grip { + display: flex; + align-items: center; + justify-content: center; + position: sticky; + top: 0; + z-index: 6; + height: 24px; + margin: 0 -14px; + background: var(--card); + touch-action: none; + cursor: grab; + } + .panel-grip::after { + content: ""; + width: 44px; + height: 5px; + border-radius: 999px; + background: #cfc6e4; + } + .panel-grip:active { cursor: grabbing; } + + body.panel-hidden #topbar { max-width: none; } + + /* The grab handle is sticky at the top of the sheet, so the action bar and the + tabs start below it. */ + .panel-topbar { top: 24px; } + .tabs { top: 58px; } +} + +/* ----------------------------------------------------------------- sections */ + +.tabs { + position: sticky; + /* Sits just below the sticky .panel-topbar (which is 34px tall). */ + top: 34px; + z-index: 3; + display: flex; + align-items: flex-end; + gap: 3px; + padding: 2px 0 0; + margin: -2px 0 8px; + border-bottom: 2px solid var(--border); + background: linear-gradient(var(--card) 72%, rgba(255, 255, 255, 0)); +} + +/* Each tab is a rounded-top tab sitting on the strip's baseline; only the icon + shows, and the active one fills with the accent and covers the baseline. */ +.tab { + flex: 1; + display: flex; + align-items: center; + justify-content: center; + font: inherit; + padding: 9px 2px 7px; + border: 1px solid var(--border); + border-bottom: none; + border-radius: 9px 9px 0 0; + background: var(--accent-soft); + color: var(--muted); + cursor: pointer; + white-space: nowrap; +} + +.tab svg { display: block; width: 20px; height: 20px; } +.tab:hover { color: var(--accent-2); border-color: var(--accent-2); } +.tab.active { + margin-bottom: -2px; + padding-bottom: 9px; + background: var(--accent); + border-color: var(--accent); + color: #fff; +} +.tab-panel[hidden] { display: none; } + +.details { + border: 1px dashed var(--border); + border-radius: 9px; + padding: 0 9px; + background: #fdfcff; +} +.details > summary { + font-size: 11px; + color: var(--muted); + cursor: pointer; + padding: 6px 0; + list-style-position: inside; +} +.details[open] > summary { color: var(--accent); } +.details-body { display: grid; gap: 8px; padding: 2px 0 9px; } + +.sec { + background: #fff; + border: 1px solid var(--border); + border-radius: var(--radius); + margin-bottom: 10px; + overflow: hidden; + box-shadow: 0 1px 2px rgba(53, 38, 90, 0.04); +} + +.sec-head { + display: flex; + align-items: center; + justify-content: space-between; + gap: 8px; + width: 100%; + padding: 10px 12px; + margin: 0; + border: 0; + background: #fff; + font: inherit; + font-size: 12.5px; + font-weight: 700; + color: #4b3a72; + text-align: left; + cursor: pointer; +} + +.sec-head .chev { color: var(--muted); font-size: 10px; transition: transform 0.18s; } +.sec.closed .chev { transform: rotate(-90deg); } +.sec-title { display: flex; align-items: center; gap: 8px; min-width: 0; } +.sec-title > span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } +.sec-icon { flex: 0 0 auto; width: 16px; height: 16px; color: var(--accent); } +.sec-body { padding: 2px 12px 12px; display: grid; gap: 9px; } +.sec.closed .sec-body { display: none; } + +/* -------------------------------------------------------------------- rows */ + +.row { display: grid; grid-template-columns: 82px minmax(0, 1fr); gap: 8px; align-items: center; } +.row.wide { grid-template-columns: 1fr; gap: 5px; } +.row > .label { font-size: 11.5px; color: var(--muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } +.control { display: flex; align-items: center; gap: 7px; min-width: 0; } +.hint { font-size: 11px; line-height: 1.55; color: var(--muted); } +.hint b { color: #5a4a7d; } +.row.is-off .control, .row.is-off > .label { opacity: 0.4; } +.row.is-off .control input { cursor: default; } +.subhead { + font-size: 10.5px; + font-weight: 700; + letter-spacing: 0.06em; + color: #8d80ab; + text-transform: uppercase; + margin-top: 3px; +} +.eye-group { + border-top: 1px solid var(--border); + margin-top: 4px; + padding-top: 8px; + display: grid; + gap: 8px; +} +.eye-group-head { + font-size: 11.5px; + font-weight: 700; + color: #6b5c92; + display: flex; + align-items: center; + gap: 6px; +} +.eye-group-head .grp-icon { color: #8a7ab8; } +.eye-group-body { display: grid; gap: 8px; } +.select { + flex: 1; + min-width: 0; + font: inherit; + font-size: 11.5px; + padding: 5px 6px; + border: 1px solid var(--border); + border-radius: 8px; + background: #fff; + color: var(--text); +} +.stack { display: grid; gap: 6px; } +.grid2 { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; } +.grid3 { display: grid; grid-template-columns: repeat(3, 1fr); gap: 6px; } + +input[type="range"] { + flex: 1; + min-width: 0; + height: 18px; + accent-color: var(--accent); + cursor: pointer; +} + +.num { + flex: 0 0 auto; + min-width: 40px; + font-size: 11px; + color: #5a4a7d; + font-variant-numeric: tabular-nums; + text-align: right; +} + +.seg { display: inline-flex; flex-wrap: wrap; padding: 2px; gap: 2px; background: #f2eff9; border-radius: 999px; } +.seg button { + font: inherit; + font-size: 11px; + padding: 4px 9px; + border: 0; + border-radius: 999px; + background: transparent; + color: var(--muted); + cursor: pointer; + white-space: nowrap; +} +.seg button.active { background: #fff; color: var(--accent); box-shadow: 0 1px 3px rgba(53, 38, 90, 0.16); } + +.btn { + font: inherit; + font-size: 11.5px; + padding: 6px 10px; + border: 1px solid var(--border); + border-radius: 8px; + background: #fff; + color: var(--text); + cursor: pointer; + white-space: nowrap; +} +.btn:hover { border-color: var(--accent-2); } +.btn.primary { background: var(--accent); border-color: var(--accent); color: #fff; } +.btn.primary:hover { background: #6b45c2; } +.btn:disabled { opacity: 0.45; cursor: default; } +.buttons { display: flex; flex-wrap: wrap; gap: 6px; } + +.chk { display: inline-flex; align-items: center; gap: 6px; font-size: 11.5px; color: #4b3a72; cursor: pointer; } +.chk input { accent-color: var(--accent); width: 14px; height: 14px; } + +.pad-wrap { display: flex; gap: 10px; align-items: center; } +.pad { + position: relative; + flex: 0 0 auto; + width: 118px; + height: 118px; + border-radius: 14px; + border: 1px solid var(--border); + background: + linear-gradient(#f0ecfa, #f0ecfa) 50% 0 / 1px 100% no-repeat, + linear-gradient(#f0ecfa, #f0ecfa) 0 50% / 100% 1px no-repeat, + #faf8ff; + cursor: crosshair; + touch-action: none; +} +.pad-dot { + position: absolute; + width: 13px; + height: 13px; + margin: -7px 0 0 -7px; + border-radius: 50%; + background: var(--accent); + box-shadow: 0 1px 4px rgba(53, 38, 90, 0.35); + pointer-events: none; +} +.pad-eye { + position: absolute; + inset: 0; + margin: auto; + width: 46px; + height: 46px; + border-radius: 50%; + border: 1px dashed #d9d1ec; + pointer-events: none; +} + +/* Tail picker: a 3x3 grid where a dot's place is the direction it means, so + the whole pad fits next to an 82px label even in a narrow panel. */ +.tail-pad { + display: grid; + grid-template-columns: repeat(3, 1fr); + grid-template-rows: repeat(3, 1fr); + place-items: center; + flex: 0 0 auto; + width: 128px; + height: 128px; + padding: 10px; + border-radius: 14px; + border: 1px solid var(--border); + background: #faf8ff; +} +.tail-dot { + width: 28px; + height: 28px; + padding: 0; + border: 0; + border-radius: 50%; + background: #ded6f0; + cursor: pointer; + transition: background 0.12s, transform 0.1s; +} +.tail-dot:hover { background: var(--accent-2); transform: scale(1.1); } +.tail-dot.active { + background: var(--accent); + box-shadow: 0 1px 4px rgba(53, 38, 90, 0.35); +} + +.swatches { display: flex; gap: 5px; flex-wrap: wrap; } +.swatch { width: 17px; height: 17px; border-radius: 5px; border: 1px solid rgba(43, 36, 51, 0.18); cursor: pointer; } +input[type="color"] { + width: 30px; + height: 22px; + padding: 0; + border: 1px solid var(--border); + border-radius: 6px; + background: #fff; + cursor: pointer; +} + +.bone-list { + max-height: 168px; + overflow-y: auto; + border: 1px solid var(--border); + border-radius: 9px; + padding: 4px; + display: grid; + gap: 2px; + background: #fcfbff; +} +.bone-item { + display: flex; + justify-content: space-between; + gap: 8px; + padding: 4px 8px; + border: 0; + border-radius: 6px; + background: transparent; + font: inherit; + font-size: 11.5px; + color: var(--text); + text-align: left; + cursor: pointer; +} +.bone-item:hover { background: #f4f0fd; } +.bone-item.active { background: var(--accent-soft); color: var(--accent); font-weight: 600; } +.bone-item small { color: var(--muted); font-size: 10.5px; } + +/* --------------------------------------------------------------------- 擬音 */ + +/* + * The stamps are painted onto the caption canvas, which is `pointer-events: + * none`, so each one gets its own transparent drag box on top - the same trick + * the bubbles use. The box follows the stamp's rotation. Its z-index sits below + * the caption handles (3), because the bubbles are drawn over the stamps and so + * must stay grabbable where the two overlap. + */ +.gion-handle { + position: absolute; + display: none; + cursor: move; + touch-action: none; + pointer-events: auto; + z-index: 2; + border: 1px dashed transparent; + border-radius: 4px; +} +.gion-handle.selected { + border-color: var(--accent); + box-shadow: 0 0 0 2px rgba(123, 83, 209, 0.18); +} + +.gion-list { display: grid; gap: 10px; } +.gion-item-head { display: flex; align-items: center; gap: 8px; } +.gion-thumb { + flex: 0 0 auto; + width: 84px; + height: 56px; + background: #f3f0fa; + border: 1px solid var(--border); + border-radius: 8px; + cursor: pointer; +} +.gion-item.active .gion-thumb { border-color: var(--accent); box-shadow: 0 0 0 2px var(--accent-soft); } + +/* The picker covers the whole window, so even a big sheet has room to draw on. */ +.gion-picker { + position: fixed; + inset: 0; + z-index: 95; + display: flex; + flex-direction: column; + gap: 10px; + padding: 16px; + background: rgba(24, 16, 44, 0.86); + backdrop-filter: blur(4px); +} +.gion-picker-bar { + display: flex; + align-items: center; + justify-content: space-between; + gap: 14px; + flex-wrap: wrap; + color: #fff; +} +.gion-picker-title { font-size: 13.5px; font-weight: 700; } +.gion-picker-actions { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; } +.gion-picker-actions .hint { color: #cfc6e6; } +.gion-picker-board { + position: relative; + flex: 1; + min-height: 0; + overflow: hidden; + border-radius: 12px; + /* A checkerboard reads as "transparent", so a PNG sheet's holes are obvious. */ + background: + linear-gradient(45deg, #2b2344 25%, transparent 25%) 0 0 / 22px 22px, + linear-gradient(-45deg, #2b2344 25%, transparent 25%) 0 11px / 22px 22px, + linear-gradient(45deg, transparent 75%, #2b2344 75%) 11px -11px / 22px 22px, + linear-gradient(-45deg, transparent 75%, #2b2344 75%) -11px 0 / 22px 22px, + #241d3a; + cursor: crosshair; + touch-action: none; +} +.gion-picker-sheet { + position: absolute; + display: block; + user-select: none; + -webkit-user-drag: none; + pointer-events: none; +} +.gion-picker-marquee { + position: absolute; + display: none; + border: 1.5px solid #fff; + background: rgba(180, 152, 255, 0.28); + box-shadow: 0 0 0 9999px rgba(20, 12, 40, 0.42); + pointer-events: none; +} + +/* -------------------------------------------------------------------- toast */ + +#notice { + position: fixed; + left: 50%; + top: 14px; + transform: translateX(-50%); + z-index: 95; + max-width: min(560px, 90vw); + padding: 10px 16px; + border-radius: 12px; + background: #fff4e5; + border: 1px solid #f0c48a; + color: #7a4a12; + font-size: 12px; + line-height: 1.65; + white-space: pre-line; + box-shadow: 0 6px 20px rgba(43, 36, 51, 0.15); +} + +#notice[hidden] { display: none; } + +/* ------------------------------------------------ 起動時のご利用について */ +#start-notice { + position: fixed; + inset: 0; + z-index: 96; + display: grid; + place-items: center; + padding: 24px; + background: rgba(43, 36, 51, 0.5); + backdrop-filter: blur(3px); +} +#start-notice[hidden] { display: none; } + +.start-sheet { + width: min(560px, 100%); + max-height: 86vh; + overflow: auto; + padding: 22px 26px; + border-radius: 16px; + background: #fff; + color: #2b2433; + box-shadow: 0 18px 50px rgba(0, 0, 0, 0.35); + font-size: 13.5px; + line-height: 1.75; +} +.start-sheet h2 { margin: 0 0 12px; font-size: 17px; } +.start-sheet p { margin: 0 0 10px; } +.start-sheet ul { margin: 0 0 12px; padding-left: 1.3em; } +.start-actions { + display: flex; + align-items: center; + justify-content: space-between; + gap: 12px; + flex-wrap: wrap; + margin-top: 16px; +} +.start-skip { display: flex; align-items: center; gap: 6px; font-size: 12px; color: #6b5d7a; } +.start-ok { + border: 0; + border-radius: 8px; + padding: 9px 22px; + background: #6b4ea8; + color: #fff; + font-size: 13.5px; + cursor: pointer; +} + +#toast { + position: fixed; + left: 50%; + bottom: 26px; + transform: translate(-50%, 14px); + z-index: 70; + padding: 8px 16px; + border-radius: 999px; + background: rgba(43, 36, 51, 0.9); + color: #fff; + font-size: 12px; + opacity: 0; + pointer-events: none; + transition: opacity 0.2s, transform 0.2s; +} +#toast.show { opacity: 1; transform: translate(-50%, 0); } + +/* ------------------------------------------------------------------ loading */ + +#loading { + position: fixed; + inset: 0; + z-index: 80; + display: grid; + place-items: center; + background: rgba(244, 242, 250, 0.94); + transition: opacity 0.35s; +} +#loading.done { opacity: 0; pointer-events: none; } + +.loading-box { text-align: center; max-width: 520px; padding: 24px; } +.loading-spinner { + width: 34px; + height: 34px; + margin: 0 auto 14px; + border-radius: 50%; + border: 3px solid #e0d8f2; + border-top-color: var(--accent); + animation: spin 0.9s linear infinite; +} +@keyframes spin { to { transform: rotate(360deg); } } +#loading-text { margin: 0; font-size: 13px; color: #5a4a7d; } +#loading-error { + margin: 12px 0 0; + font-size: 12px; + line-height: 1.7; + color: #b3261e; + white-space: pre-wrap; + text-align: left; +} + +/* --------------------------------------------------------------------- help */ + +#help { + position: fixed; + inset: 0; + z-index: 90; + display: grid; + place-items: center; + padding: 24px; + background: rgba(43, 36, 51, 0.42); + backdrop-filter: blur(3px); +} +#help[hidden] { display: none; } + +.help-sheet { + position: relative; + width: min(760px, 100%); + max-height: min(84vh, 900px); + overflow-y: auto; + padding: 26px 30px 32px; + background: #fff; + border-radius: 18px; + box-shadow: 0 24px 60px rgba(20, 12, 40, 0.3); + font-size: 13px; + line-height: 1.75; +} +.help-sheet h2 { margin: 0 0 14px; font-size: 17px; color: #4b3a72; } +.help-sheet h3 { margin: 20px 0 6px; font-size: 13.5px; color: var(--accent); } +.help-sheet ul { margin: 0; padding-left: 1.25em; } +.help-sheet li { margin: 3px 0; } +.help-sheet code { background: #f3f0fa; padding: 1px 5px; border-radius: 5px; font-size: 12px; } +.help-sheet .keys { list-style: none; padding: 0; display: grid; gap: 4px; } +.help-close { + position: absolute; + top: 12px; + right: 14px; + width: 32px; + height: 32px; + border: 0; + border-radius: 50%; + background: #f3f0fa; + color: #5a4a7d; + font-size: 19px; + line-height: 1; + cursor: pointer; +} +.help-close:hover { background: #e8e2f7; } + +kbd { + display: inline-block; + min-width: 20px; + padding: 1px 6px; + border: 1px solid var(--border); + border-bottom-width: 2px; + border-radius: 5px; + background: #faf9fe; + font: inherit; + font-size: 11px; + text-align: center; +} + +/* The always-visible action bar above the tabs: 元に戻す / やり直す / すべてランダム. + Sticky, so it (and the tabs below it) stay on screen while the panel scrolls. */ +.panel-topbar { + position: sticky; + top: 0; + z-index: 5; + background: #fdfcff; + display: flex; + gap: 4px; + justify-content: flex-end; + padding: 4px 8px 2px; +} +.panel-topbar .icon-btn { + display: inline-flex; + align-items: center; + justify-content: center; + width: 32px; + height: 28px; + padding: 0; + border: 1px solid var(--border); + border-radius: 8px; + background: #fff; + color: #2b2433; + cursor: pointer; +} +.panel-topbar .icon-btn:hover { background: #f4f0fb; } +.panel-topbar .icon-btn:active { transform: translateY(1px); } |
