
:root {
color-scheme: dark;

/* Accent. #007bff is tuned for light backgrounds and only reached 4.19:1 on the
   dark shell (3.51:1 on cards), which is below AA for the result readout.
   This blue reads at 6.35:1 while keeping the same hue. */
--primary: #4da3ff;
--primary-hover: #7cbcff;
--primary-contrast: #08243d;
/* The expression input is focused nearly all the time, so its ring is effectively a
   permanent border. Bright accent there was glaring and lights up OLED pixels; this
   dim blue stays visible without drawing attention (or power). */
--focus-ring-dim: #2b4a66;
--danger: #ff6b7a;
--danger-hover: #ff9099;

/* Surfaces, from furthest back to closest. */
--bg-color: #1e1e1e;
--card-bg: #2c2c2c;
--input-bg: #3a3a3a;
--surface-sunken: #303030;
--overlay-scrim: rgba(0, 0, 0, 0.6);
--overlay-scrim-strong: rgba(0, 0, 0, 0.82);
--toast-bg: rgba(0, 0, 0, 0.88);
--overlay-scrim-max: rgba(0, 0, 0, 0.9);

/* Lines and dividers. */
--border: #555;
--divider-soft: rgba(255, 255, 255, 0.1);
--divider-faint: rgba(255, 255, 255, 0.09);

/* Text. */
--text: #f0f0f0;
--text-strong: #ffffff;
--text-secondary: #d4d7dc;
--timestamp: #a0a0a0;
--text-muted: #aaaaaa;
--text-disabled: #cfcfcf;

/* Controls. */
--key-active-bg: #4a4a4a;
--key-hold-bg: #353535;
--key-longpress-bg: #565656;
--control-neutral: #666666;
--control-neutral-strong: #5a5a5a;
--control-disabled-bg: #4b4b4b;
--checkbox-bg: #707070;
--checkbox-border: #909090;
--checkbox-bg-checked: #858585;
--checkbox-border-checked: #a8a8a8;
--checkbox-tick: #f5f5f5;
--scrollbar-thumb: #8a8a8a;
--scrollbar-track: var(--surface-sunken);
/* Wide on purpose so the thumb stays draggable by thumb; tune here, not per-rule. */
--scrollbar-width: 18px;

/* Elevation. The card shadow changes direction per layout, so only its colour is
   shared; the offsets stay at the call site. */
--shadow-card-color: rgba(0, 0, 0, 0.3);
--shadow-modal: 0 18px 60px rgba(0, 0, 0, 0.58);

/* Motion. One switch so prefers-reduced-motion can zero everything out. */
--motion-fast: 0.18s;
--motion-normal: 0.3s;

--app-visible-height: 100dvh;
--app-container-height: calc(100dvh - 30px);
--app-bottom-bar-height: 30px;
/* Minimum only. The readout grows to a second line for long results such as
   the "expression = decimal (quotient r remainder)" form. */
--result-display-height: 24px;
--current-list-height: 0px;
--history-list-height: 0px;
--page-edge-padding: 10px;
--book-bar-height: 48px;
--page-top-padding: calc(env(safe-area-inset-top, 0px) + var(--book-bar-height) + 6px);
}

/* 折叠模式下，实时结果区域兼职当"移动光标的触控板"，需要比列表模式下更高的
   触控面积；数值只在折叠模式下覆盖，不影响列表模式原有高度。24px 的三分之一
   是 8px，加高后 32px。这条变量在 body 上覆盖，靠 CSS 自定义属性的继承，
   .card 的 grid-template-rows 和 .result-display 的 min-height 两处引用
   的都是同一个值，不会出现"显示区域变高了，但栅格行没跟着长"的错位。 */
body.folded-view-mode { --result-display-height: 32px; }
body.folded-view-mode .result-display {
cursor: ew-resize;
touch-action: none;
-webkit-user-select: none;
user-select: none;
}

@supports not (height: 100dvh) {
:root {
--app-visible-height: 100vh;
--app-container-height: calc(100vh - 30px);
}
}

* {
box-sizing: border-box;
}

body {
margin: 0;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", sans-serif;
background-color: var(--bg-color);
color: var(--text);
-webkit-font-smoothing: antialiased;
user-select: none;
-webkit-tap-highlight-color: transparent;
min-height: 100vh;
min-height: var(--app-visible-height);
height: var(--app-visible-height);
display: flex;
flex-direction: column;
align-items: center;
padding:
  var(--page-top-padding)
  max(env(safe-area-inset-right, 0px), var(--page-edge-padding))
  max(env(safe-area-inset-bottom, 0px), var(--page-edge-padding))
  max(env(safe-area-inset-left, 0px), var(--page-edge-padding));
overflow: hidden;
}

.container {
max-width: 480px;
width: 100%;
display: flex;
flex-direction: column;
height: calc(100vh - 30px); /* Adjust for bottom-bar */
height: var(--app-container-height);
overflow: hidden;
padding: 10px;
box-sizing: border-box;
transition: height 0.18s ease;
}

.history-pane {
display: contents;
}

.wide-current-panel {
display: none;
}

.portrait-current-panel {
flex: 0 1 clamp(64px, 16vh, 120px);
min-height: 56px;
overflow: hidden;
border: 1px solid var(--border);
border-radius: 8px;
background-color: var(--input-bg);
clip-path: inset(0 round 8px);
contain: paint;
}

.card {
background-color: var(--card-bg);
border-radius: 12px;
padding: 12px;
box-shadow: 0 -5px 15px var(--shadow-card-color);
display: flex;
flex-direction: column;
gap: 8px;
z-index: 100;
flex-shrink: 0;
margin-top: auto;
width: 100%;
max-height: 100%;
overflow: hidden;
}

.input-group {
display: flex;
gap: 8px;
flex-wrap: wrap;
justify-content: space-between;
align-items: center;
margin: 0;
position: relative;
}

/* 任务C折叠视图：expressionInput 本身还是真正的数据源（value/selectionStart），
   一个 <input> 没法让部分文字压暗、部分高亮、外面再套不可编辑的装饰括号——这层
   overlay 顶在它上面画视觉，点击换算成坐标后转发成 expressionInput.setSelectionRange，
   两边永远同步。列表模式下 overlay 不显示，expressionInput 自己正常渲染。 */
#foldedOverlay {
position: absolute;
inset: 0;
display: none;
align-items: center;
overflow-x: auto;
overflow-y: hidden;
white-space: nowrap;
padding: 12px 8px;
font-size: 1.1rem;
border-radius: 8px;
background-color: var(--input-bg);
box-sizing: border-box;
}
#foldedOverlay.active { display: flex; }
/* flex 子项默认 flex-shrink:1，内容一旦比输入框宽就会被压缩变形（长数字打
   到一半开始挤在一起、看起来像光标在跳），而不是让 overflow-x:auto 生效滚动。
   全部设成不收缩，该溢出就溢出，交给下面的 seg-caret 滚动到可见区。 */
#foldedOverlay > * { flex-shrink: 0; }
#foldedOverlay .seg-connector { color: var(--text); padding: 0 1px; }
#foldedOverlay .seg-connector.muted-connector { color: var(--timestamp); }
#foldedOverlay .seg-muted { color: var(--timestamp); cursor: pointer; }
#foldedOverlay .seg-char { color: var(--text-muted); display: inline-block; }
#foldedOverlay .seg-char.highlighted-char { color: var(--text); }
#foldedOverlay .seg-tail { flex: 0 0 24px; min-width: 24px; align-self: stretch; cursor: text; }
#foldedOverlay .seg-caret {
display: inline-block;
width: 3px;
height: 1.25em;
background: var(--primary);
vertical-align: middle;
margin: 0 -1.5px;
border-radius: 1.5px;
box-shadow: 0 0 3px var(--primary);
animation: folded-caret-blink 1s step-start infinite;
}
@keyframes folded-caret-blink { 50% { opacity: 0; } }
/* 触控板拖动/单击移动光标的过程中，光标本来就应该跟手、全程可见，不该被
   1s 一次的闪烁动画顶得时隐时现——用户在快速滑动时如果正好瞟到"熄灭"的
   那一半周期，看起来就跟光标真的消失了一样。交互进行中强制常亮，松手后
   再恢复正常的闪烁提示。*/
#foldedOverlay.touchpad-active .seg-caret {
animation: none;
opacity: 1;
}

input[type="text"], .remarks-input {
width: 100%;
padding: 12px 8px;
border-radius: 8px;
border: none;
background-color: var(--input-bg);
color: var(--text);
user-select: text;
box-sizing: border-box;
}

/* The input had outline:none with no replacement, so with a hardware keyboard there
   was no way to tell it held focus. An inset ring avoids shifting layout. */
input[type="text"]:focus, .remarks-input:focus {
outline: none;
border: none;
box-shadow: inset 0 0 0 2px var(--focus-ring-dim);
}

/* Keyboard-only focus ring for everything else. Pointer taps stay unchanged. */
button:focus-visible,
select:focus-visible,
input:focus-visible,
[tabindex]:focus-visible {
outline: 2px solid var(--primary);
outline-offset: 2px;
}

.key:focus-visible {
outline-offset: -3px;
}

::selection {
background: var(--primary);
color: var(--primary-contrast);
}

::placeholder {
color: var(--timestamp);
opacity: 1;
}

/* Hover only where a real pointer exists: tablets, DeX, Chromebooks.
   Guarded so touch devices never get stuck in a hover state after a tap. */
@media (hover: hover) and (pointer: fine) {
.key:hover { background-color: var(--key-hold-bg); }
.op-key:hover { background-color: var(--key-hold-bg); }
button:hover { filter: brightness(1.12); }
.history-entry:hover { background-color: var(--key-hold-bg); }
li:hover { background-color: var(--divider-faint); }
}

input[type="text"] {
flex-grow: 1;
min-width: 120px;
max-width: 100%;
font-size: 1.1rem;
text-align: center;
}

#expressionInput.inline-text-mode {
text-align: left;
color: var(--text);
-webkit-text-fill-color: var(--text);
}

body.system-text-input-active #foldedOverlay {
display: none !important;
pointer-events: none;
}

/* 备注和搜索把输入交给系统输入法，此时计算器键盘必须让路，屏幕上只留
   输入框、历史列表和系统键盘。
   本来有一组 body.system-keyboard-open.system-text-input-active 的规则在做
   这件事，但它整组写在 @media (orientation: landscape) and (min-width:560px),
   (min-width:700px) 里面——竖屏手机根本不匹配，于是写备注时计算器键盘一直
   杵在那儿。这里按输入模式无条件收起，不依赖屏幕尺寸，也不依赖"系统键盘是
   否已被检测到弹出"（检测有阈值和延迟，靠它会闪一下）。
   entryEdit 不在此列：它用的就是计算器键盘（inputmode=none）。 */
body.system-text-input-active #custom-keyboard {
display: none !important;
}

body.system-text-input-active .card > .portrait-current-panel,
body.system-text-input-active .card .result-display {
display: none;
}

body.system-text-input-active .card {
height: auto;
min-height: 0;
max-height: none;
flex: 0 0 auto;
}

body.system-text-input-active #expressionInput {
min-height: 46px;
padding: 12px 10px;
}

/* 同款遗漏：宽屏那份 body.system-keyboard-open.system-text-input-active
   #history-container{height:100%} 也整组写在宽屏 media query 里，竖屏手机
   打备注时命中不到，历史列表只按内容撑到一行高，键盘弹起后中间空出一大截、
   看起来像"历史记录不见了"。这里不分屏幕宽窄，键盘真弹起时都把历史列表
   撑满剩余空间，和苹果原生一样，把正在写备注的那条留在看得见的地方。 */
body.system-keyboard-open.system-text-input-active #history-container {
height: 100%;
flex: 1 1 auto;
}

button {
border: none;
border-radius: 6px;
font-size: 0.95rem;
font-weight: 500;
cursor: pointer;
padding: 8px 12px;
transition: background-color 0.2s ease, transform 0.1s ease;
user-select: none;
min-width: 50px;
flex-shrink: 0;
}

button:active {
transform: scale(0.98);
}

/* The readout must fit the full "expression = decimal (quotient 余 remainder)" form.
   It used to be locked to a single 23.333px line with overflow:hidden, so any longer
   result silently lost its second line. It now grows to two lines and only then
   ellipsises, so truncation is at least visible. */
.result-display {
text-align: center;
font-size: 1.1rem;
font-weight: bold;
min-height: var(--result-display-height);
margin: 0;
color: var(--primary);
/* 新版 Chrome 只要检测到 -webkit-line-clamp，就会把 display 强制
   变成 flow-root（不管你写的是 -webkit-box 还是别的），导致
   -webkit-box-pack/-webkit-box-align 和 flex 的 align-items/
   justify-content 全部失效，内容永远贴顶。所以居中交给这一层的
   flex，两行截断的活儿挪到下面 #result 那个子元素上去做。 */
display: flex;
align-items: center;
justify-content: center;
overflow: hidden;
}

#result {
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 2;
line-clamp: 2;
line-height: 1.2;
overflow-wrap: anywhere;
overflow: hidden;
width: 100%;
}

ul {
list-style: none;
padding: 0;
margin: 0;
max-height: 200px;
overflow-y: auto;
border: none;
border-radius: 6px;
background-color: transparent;
}

#current-numbers-list {
height: 100%;
max-height: none;
overflow-y: auto;
-webkit-overflow-scrolling: touch;
min-height: 0;
border-radius: 7px;
}

li {
padding: 6px 10px;
border-bottom: 1px solid var(--border);
display: flex;
justify-content: space-between;
align-items: center;
font-size: 0.9rem;
cursor: pointer;
user-select: none;
}

li:last-child {
border-bottom: none;
}

.time-stamp {
font-size: 0.65rem;
color: var(--timestamp);
flex-shrink: 0;
margin-left: 6px;
}

#history-container {
flex: 1;
min-height: 0;
overflow-y: auto;
-webkit-overflow-scrolling: touch;
/* 防止列表的橡皮筋回弹把滚动手势"泄漏"给页面其它部分，也能减少
   刚好停在滚动边界时把点击吞掉的概率。 */
overscroll-behavior-y: contain;
display: flex;
flex-direction: column;
gap: 0;
padding: 0;
border: 1px solid var(--border);
border-radius: 12px;
background-color: var(--input-bg);
margin-bottom: 10px;
clip-path: inset(0 round 12px);
contain: paint;
isolation: isolate;
padding-top: 0;
}

.legal-info-button {
position: fixed;
top: max(calc(env(safe-area-inset-top, 0px) + 4px), 4px);
right: max(calc(env(safe-area-inset-right, 0px) + 4px), 4px);
z-index: 9000;
/* Was 32px, below the 44px minimum touch target and awkward to hit in the corner. */
width: 44px;
height: 44px;
min-width: 44px;
min-height: 44px;
padding: 0;
/* 用 flex 居中而不是只靠 line-height，不同平台的 WebView（WKWebView /
   ArkWeb / Chromium）对按钮内在 padding 和文字基线的处理不完全一致，
   仅靠 line-height:1 在有些机型上会让"ⓘ"上下偏移，flex 居中更稳。 */
display: flex;
align-items: center;
justify-content: center;
/* 去掉了外面的圆形描边/背景/投影，只留图标本身，视觉上更轻。 */
border: none;
background: transparent;
color: var(--timestamp);
}

.legal-info-button:active { transform: scale(0.9); opacity: 0.7; }

.history-entry {
background-color: var(--input-bg);
border-bottom: 1px solid var(--border);
padding: 8px;
flex: 0 0 auto;
}

/* Was leaving a stray divider at the bottom of the list, masked only by the clip-path. */
.history-entry:last-child {
border-bottom: none;
}

.history-entry label {
display: flex;
gap: 6px;
align-items: center;
min-height: 32px;
cursor: pointer;
user-select: none;
}

.history-content {
min-width: 0;
flex: 1;
}

.history-expression {
font-size: 0.85rem;
color: var(--text);
margin: 4px 0;
padding-left: 10px;
word-break: break-all;
}

.history-summary {
font-size: 1rem;
color: var(--text);
word-break: break-all;
line-height: 1.35;
}

.remainder-decimal {
display: inline-block;
white-space: nowrap;
}

.history-summary-time {
color: var(--text-muted);
font-size: 0.8em;
font-weight: 400;
margin-left: 6px;
white-space: nowrap;
}

.history-entry p {
margin: 0 0 4px 0;
font-weight: 600;
}

.history-remark {
display: inline-block;
font-size: 0.8rem;
color: var(--primary);
margin-left: 6px;
white-space: nowrap;
font-style: italic;
vertical-align: baseline;
}

#remarkModal {
display: none;
position: fixed;
inset: 0;
background: var(--overlay-scrim);
justify-content: center;
align-items: center;
z-index: 10002;
}

#remarkModalContent {
background: var(--card-bg);
padding: 10px;
border-radius: 8px;
width: 90%;
max-width: 300px;
box-sizing: border-box;
}

#remarkModalContent h3 { margin: 0 0 4px 0; color: var(--primary); }

#remarkTextarea {
width: 100%;
padding: 8px;
font-size: 0.9rem;
border-radius: 6px;
border: 1px solid var(--border);
background-color: var(--input-bg);
color: var(--text);
box-sizing: border-box;
min-height: 80px;
resize: none;
}

#remarkButtons { margin-top: 8px; text-align: right; }

#remarkCancelBtn, #remarkConfirmBtn {
padding: 4px 8px;
border-radius: 5px;
border: none;
cursor: pointer;
user-select: none;
}

#remarkCancelBtn { margin-right: 4px; background-color: var(--control-neutral); color: var(--text-strong); }
#remarkConfirmBtn { background-color: var(--primary); color: var(--primary-contrast); }

/* ---- 多任务计算本：常驻屏幕顶部的固定条，不随内容滚动 ---- */
#bookBar {
display: none;
align-items: center;
gap: 10px;
position: fixed;
top: 0;
left: 0;
right: 0;
margin: 0 auto;
max-width: 480px;
width: 100%;
box-sizing: border-box;
min-height: calc(env(safe-area-inset-top, 0px) + var(--book-bar-height));
/* 右边留出空间，避免被右上角的开源许可圆形按钮（44px + 边距）盖住 */
padding: calc(env(safe-area-inset-top, 0px) + 4px) 56px calc(4px) 12px;
border: 0;
border-bottom: 1px solid var(--border);
border-radius: 0;
background: var(--card-bg);
color: var(--timestamp);
font-size: 1.45rem;
line-height: 1.25;
text-align: left;
overflow: hidden;
z-index: 1000;
}
#bookBar.visible { display: flex; }
#bookBarName {
flex: 1 1 auto;
min-width: 0;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
color: var(--text-secondary);
font-weight: 600;
/* 去掉了左侧的“=”图标按钮，标题栏不再需要为它留出视觉重量，字号放大到跟
   #bookBarCount（"暂无记录" 等文案）一致，都继承 #bookBar 的 1.45rem。 */
}
#bookBarCount { flex: 0 0 auto; color: var(--timestamp); }

#bookModal {
display: none;
position: fixed;
inset: 0;
background: var(--overlay-scrim);
justify-content: center;
align-items: center;
z-index: 10004;
}
#bookModalContent {
display: flex;
flex-direction: column;
width: 90%;
max-width: 340px;
max-height: 80vh;
padding: 12px;
box-sizing: border-box;
border-radius: 8px;
background: var(--card-bg);
}
#bookModalContent h3 { margin: 0 0 8px; color: var(--primary); font-size: 1.05rem; }
#bookList {
flex: 1 1 auto;
min-height: 0;
margin: 0 0 10px;
padding: 0;
overflow-y: auto;
list-style: none;
}
.book-item {
display: flex;
align-items: center;
gap: 8px;
padding: 9px 10px;
margin-bottom: 6px;
border: 1px solid var(--border);
border-radius: 6px;
background: var(--input-bg);
cursor: pointer;
}
.book-item.active { border-color: var(--primary); }
.book-item-main { flex: 1 1 auto; min-width: 0; }
.book-item-name {
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
color: var(--text);
font-size: 0.92rem;
}
.book-item.active .book-item-name { color: var(--primary); font-weight: 600; }
.book-item-meta { margin-top: 2px; color: var(--timestamp); font-size: 0.74rem; }
.book-item-actions { display: flex; flex: 0 0 auto; gap: 4px; }
.book-item-actions button {
min-width: 30px;
min-height: 30px;
padding: 0 6px;
border: 0;
border-radius: 5px;
background: var(--control-neutral);
color: var(--text-strong);
font-size: 0.78rem;
}
/* 有历史记录的计算本不能删除，按钮置灰 */
.book-item-actions button:disabled {
background: var(--control-disabled-bg);
color: var(--text-disabled);
cursor: default;
}

/* 应用内对话框：替代 window.confirm / window.prompt，
   浏览器原生弹窗在 WebView 里与应用风格割裂，且无法本地化按钮文字。 */
#appDialog {
display: none;
position: fixed;
inset: 0;
padding: 20px;
background: var(--overlay-scrim-max);
align-items: center;
justify-content: center;
z-index: 10010;
}
#appDialogPanel {
width: min(100%, 320px);
padding: 20px;
border-radius: 14px;
background: var(--card-bg);
box-shadow: var(--shadow-modal);
text-align: center;
}
#appDialogTitle {
margin: 0;
color: var(--text-strong);
font-size: 1.05rem;
line-height: 1.4;
word-break: break-word;
}
#appDialogMessage {
margin: 8px 0 0;
color: var(--text-secondary);
font-size: 0.88rem;
line-height: 1.6;
white-space: pre-line;
}
#appDialogInput {
width: 100%;
margin-top: 14px;
padding: 11px 12px;
box-sizing: border-box;
border: 1px solid var(--border);
border-radius: 8px;
background: var(--input-bg);
color: var(--text);
font-size: 1rem;
text-align: center;
}
#appDialogActions {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 10px;
margin-top: 18px;
}
#appDialogActions button {
min-height: 46px;
border: 0;
border-radius: 10px;
font-size: 1rem;
cursor: pointer;
user-select: none;
}
#appDialogCancel { background: var(--control-neutral-strong); color: var(--text-strong); }
#appDialogConfirm { background: var(--primary); color: var(--primary-contrast); }
/* --danger 是亮粉红，白字只有 2.75:1；深色文字可达 5.74:1 */
#appDialogConfirm.danger { background: var(--danger); color: var(--primary-contrast); }
#bookModalActions { display: flex; flex: 0 0 auto; gap: 6px; }
#bookModalActions button { flex: 1; min-height: 40px; border: 0; border-radius: 6px; font-size: 0.88rem; }
#bookNewBtn { background: var(--primary); color: var(--primary-contrast); }
#bookCloseBtn { background: var(--control-neutral); color: var(--text-strong); }

#searchModal {
display: none;
position: fixed;
inset: 0;
background: var(--overlay-scrim);
justify-content: center;
align-items: center;
z-index: 10003;
}

#searchModalContent {
background: var(--card-bg);
padding: 10px;
border-radius: 8px;
width: 90%;
max-width: 300px;
box-sizing: border-box;
}

#searchModalContent h3 { margin: 0 0 4px 0; color: var(--primary); }

#searchQueryInput {
width: 100%;
padding: 8px;
font-size: 0.9rem;
border-radius: 6px;
border: 1px solid var(--border);
background-color: var(--input-bg);
color: var(--text);
box-sizing: border-box;
}

#searchButtons { margin-top: 8px; text-align: right; }

#searchCancelBtn, #searchConfirmBtn {
padding: 4px 8px;
border-radius: 5px;
border: none;
cursor: pointer;
user-select: none;
}

#searchCancelBtn { margin-right: 4px; background-color: var(--control-neutral); color: var(--text-strong); }
#searchConfirmBtn { background-color: var(--primary); color: var(--primary-contrast); }

input[type="checkbox"] {
width: 1.4em;
height: 1.4em;
cursor: pointer;
}

input.history-checkbox {
appearance: none;
-webkit-appearance: none;
position: relative;
flex: 0 0 1.25em;
width: 1.25em;
height: 1.25em;
margin: 0;
border: 1px solid var(--checkbox-border);
border-radius: 3px;
background-color: var(--checkbox-bg);
}

input.history-checkbox:checked {
background-color: var(--checkbox-bg-checked);
border-color: var(--checkbox-border-checked);
}

input.history-checkbox:checked::after {
content: "";
position: absolute;
left: 4px;
top: 1px;
width: 4px;
height: 8px;
border: solid var(--checkbox-tick);
border-width: 0 2px 2px 0;
transform: rotate(45deg);
}

#custom-keyboard {
display: grid;
grid-template-columns: 2.3fr 1.3fr 1.3fr 1.5fr;
grid-template-rows: repeat(5, 44px);
gap: 1px;
padding: 0;
background-color: transparent;
width: 100%;
z-index: 100;
transition: max-height 0.3s ease-out, opacity 0.3s ease-out, margin-top 0.3s ease-out;
max-height: 0;
opacity: 0;
overflow: hidden;
transform-origin: center;
}

#custom-keyboard.visible {
max-height: 300px;
opacity: 1;
margin-top: 0;
}

.key {
padding: 2px 6px;
font-size: 1rem;
font-weight: 500;
text-align: center;
background-color: var(--input-bg);
color: var(--text);
border: none;
border-radius: 6px;
cursor: pointer;
user-select: none;
position: relative;
overflow: hidden;
isolation: isolate;
transition: background-color 90ms ease-out, color 90ms ease-out, box-shadow 90ms ease-out, transform 90ms ease-out;
display: flex;
justify-content: center;
align-items: center;
min-height: 0;
height: 44px;
touch-action: none;
}

.key:active, .key.key-active {
background-color: var(--key-active-bg);
box-shadow: inset 0 2px 5px rgba(0, 0, 0, 0.42), inset 0 0 0 1px rgba(104, 104, 104, 0.16);
transform: translateY(1px) scale(0.985);
}

.key.key-hold-ready {
background-color: var(--key-hold-bg);
background-image: linear-gradient(90deg, var(--key-active-bg), var(--key-active-bg));
background-repeat: no-repeat;
background-position: left center;
background-size: 0 100%;
box-shadow: inset 0 2px 6px rgba(0, 0, 0, 0.52), inset 0 0 0 1px rgba(104, 104, 104, 0.16);
animation: key-hold-fill var(--key-hold-remaining, 250ms) linear forwards;
}

.key.key-long-press {
background-color: var(--key-longpress-bg);
animation: key-long-press-confirm 210ms ease-out;
}

@keyframes key-hold-fill {
from { background-size: 0 100%; }
to { background-size: 100% 100%; }
}

@keyframes key-long-press-confirm {
0% { box-shadow: inset 0 2px 6px rgba(0, 0, 0, 0.52), 0 0 0 1px rgba(104, 104, 104, 0.34); }
100% { box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.34); }
}

body.left-hand-mode #custom-keyboard {
transform: scaleX(-1);
}

body.left-hand-mode #custom-keyboard .key {
transform: scaleX(-1);
}

body.left-hand-mode #custom-keyboard .key:active,
body.left-hand-mode #custom-keyboard .key.key-active {
transform: scaleX(-1) translateY(1px) scale(0.985);
}

body.left-hand-mode #custom-keyboard .key[data-key="1"] {
grid-column: 4;
grid-row: 1;
}

body.left-hand-mode #custom-keyboard .key[data-key="2"] {
grid-column: 3;
grid-row: 1;
}

body.left-hand-mode #custom-keyboard .key[data-key="3"] {
grid-column: 2;
grid-row: 1;
}

body.left-hand-mode #custom-keyboard .key[data-key="4"] {
grid-column: 4;
grid-row: 2;
}

body.left-hand-mode #custom-keyboard .key[data-key="5"] {
grid-column: 3;
grid-row: 2;
}

body.left-hand-mode #custom-keyboard .key[data-key="6"] {
grid-column: 2;
grid-row: 2;
}

body.left-hand-mode #custom-keyboard .key[data-key="7"] {
grid-column: 4;
grid-row: 3;
}

body.left-hand-mode #custom-keyboard .key[data-key="8"] {
grid-column: 3;
grid-row: 3;
}

body.left-hand-mode #custom-keyboard .key[data-key="9"] {
grid-column: 2;
grid-row: 3;
}

body.left-hand-mode #custom-keyboard .key[data-key="0"] {
grid-column: 4;
grid-row: 4;
}

body.left-hand-mode #custom-keyboard .key[data-key="."] {
grid-column: 3;
grid-row: 4;
}

body.left-hand-mode #custom-equals-key {
grid-column: 2;
grid-row: 4;
}

body.left-hand-mode #custom-keyboard .key[data-key="()"] {
grid-column: 1;
grid-row: 5;
}

body.left-hand-mode #backspace-key {
grid-column: 4;
grid-row: 5;
}

body.left-hand-mode #long-equals-key {
grid-column: 2 / span 2;
grid-row: 5;
}

.op-key {
font-family: Arial, sans-serif;
color: white;
font-size: 1.8rem;
padding: 2px 6px;
line-height: normal;
}

.op-key.active {
color: var(--primary);
}


#long-equals-key {
grid-column: span 2;
}

#backspace-key {
font-size: 1rem;
}

/* 折叠模式不给手动括号键：活动组模型已经证明自动/手动括号在数据层面物理
   隔离，剩下的只是密集单行里"会不会看糊涂"的纯 UI 问题，干脆不暴露这个键，
   腾出的位置给更高频的退格键。要打嵌套括号切到列表模式打，同一份 entries，
   切回来照常显示，不损失表达力。（跟原生 Keypad.tail 的折叠规则一致。） */
#custom-keyboard.folded-mode .key[data-key="()"] { display: none; }
#custom-keyboard.folded-mode #backspace-key { grid-column: 1 / span 2; grid-row: 5; }
#custom-keyboard.folded-mode #long-equals-key { grid-column: 3 / span 2; grid-row: 5; }
body.left-hand-mode #custom-keyboard.folded-mode #backspace-key { grid-column: 3 / span 2; grid-row: 5; }
body.left-hand-mode #custom-keyboard.folded-mode #long-equals-key { grid-column: 1 / span 2; grid-row: 5; }

/* Backdrop behind the system navigation bar in edge-to-edge mode. A flat 30px does not
   match reality: gesture navigation is about 24dp and the 3-button bar about 48dp, so it
   either left a gap or overdrew. Track the real inset and keep 30px as the floor. */
#bottom-bar {
position: fixed;
bottom: 0;
left: 0;
width: 100%;
height: 30px;
height: max(var(--app-bottom-bar-height), env(safe-area-inset-bottom, 0px));
background-color: var(--bg-color);
z-index: 9999;
transition: height var(--motion-fast) ease, opacity var(--motion-fast) ease;
pointer-events: none;
display: flex;
align-items: center;
justify-content: center;
gap: clamp(10px, 4vw, 18px);
padding: 2px max(18px, env(safe-area-inset-right, 0px)) calc(6px + env(safe-area-inset-bottom, 0px)) max(18px, env(safe-area-inset-left, 0px));
box-sizing: border-box;
}
.store-link {
height: 22px;
min-height: 22px;
min-width: 0;
width: 132px;
max-width: 132px;
flex: 0 1 132px;
display: inline-flex;
align-items: center;
justify-content: center;
gap: 5px;
padding: 2px 8px;
border-radius: 7px;
background: var(--control-neutral-strong, #161616);
border: 1px solid color-mix(in srgb, var(--text) 18%, transparent);
color: var(--text);
text-decoration: none;
font: 600 0.6rem/1 -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
letter-spacing: .01em;
transition: transform var(--motion-fast) ease, background var(--motion-fast) ease;
pointer-events: auto;
box-sizing: border-box;
}
.store-link:active { transform: scale(.97); }
.store-link svg { width: 11px; height: 11px; flex: 0 0 auto; }
.store-link span { white-space: nowrap; }
.store-slot-empty { pointer-events: none; }
@media (max-width: 380px) {
#bottom-bar { gap: 14px; padding-inline: max(14px, env(safe-area-inset-left, 0px)); }
.store-link { padding-inline: 6px; font-size: .58rem; }
.store-link svg { width: 10px; height: 10px; }
}
@media (min-width: 900px) {
.store-link { width: 150px; max-width: 150px; flex-basis: 150px; }
}

body.system-keyboard-open {
--app-bottom-bar-height: 0px;
}

body.system-keyboard-open #bottom-bar {
opacity: 0;
}

@media (max-width: 480px) {
body { --page-edge-padding: 5px; }
.card { padding: 8px; gap: 4px; }
input[type="text"] { max-width: 100%; min-width: unset; font-size: 1rem; padding: 10px 6px; }
.result-display { font-size: 1.1rem; }
ul { max-height: 305px; }
.portrait-current-panel { flex-basis: clamp(56px, 14vh, 96px); min-height: 52px; }
li { padding: 4px 8px; font-size: 0.85rem; }
#history-container { max-height: unset; }
.input-group { flex-direction: row; align-items: center; gap: 4px; }
.history-entry { padding: 6px; }
.history-expression { font-size: 0.8rem; margin: 2px 0; padding-left: 8px; }
.time-stamp { font-size: 0.6rem; margin-left: 4px; }
/* 44px is the minimum comfortable touch target; this breakpoint covers most phones,
   so it previously shipped 40px keys to the majority of users. */
#custom-keyboard.visible { grid-template-rows: repeat(5, 44px); }
.op-key { font-size: 2.2rem; padding: 2px 6px; }
.key { min-height: 0; height: 44px; padding: 2px 6px; }
}

@media (orientation: landscape) and (min-width: 560px), (min-width: 700px) {
body {
--page-edge-padding: 6px;
}

.container {
max-width: none;
display: grid;
grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
gap: 10px;
padding: 6px;
}

.history-pane {
display: flex;
flex-direction: column;
min-width: 0;
min-height: 0;
gap: 0;
}

#history-container {
width: 100%;
height: 100%;
flex: 1 1 auto;
margin-bottom: 0;
border-radius: 8px;
clip-path: inset(0 round 8px);
padding-top: 0;
}

.card > .portrait-current-panel { padding-top: 0; }

body.left-hand-mode #history-container { padding-top: 0; }
body.left-hand-mode .card > .portrait-current-panel { padding-top: 0; }

.wide-current-panel {
display: none;
}

#wide-current-numbers-list {
height: 100%;
max-height: none;
overflow-y: auto;
-webkit-overflow-scrolling: touch;
border-radius: 7px;
}

.card {
width: 100%;
height: 100%;
min-width: 0;
margin-top: 0;
padding: 8px;
gap: 4px;
border-radius: 8px;
box-shadow: -5px 0 15px var(--shadow-card-color);
display: grid;
/* auto-sized so a two-line result is not cropped by a fixed track */
grid-template-rows: minmax(0, 1fr) auto minmax(var(--result-display-height), auto) auto;
align-items: stretch;
}

.card > .portrait-current-panel {
display: block;
height: 100%;
min-height: 0;
flex: none;
}

.card .result-display {
min-height: var(--result-display-height);
margin: 0;
overflow: hidden;
}

#custom-keyboard.visible {
flex-shrink: 0;
align-self: end;
margin-top: 0;
height: auto;
max-height: 300px;
}

body.system-keyboard-open.system-text-input-active .wide-current-panel {
display: none;
}

body.system-keyboard-open.system-text-input-active .history-pane {
gap: 0;
}

body.system-keyboard-open.system-text-input-active #history-container {
height: 100%;
}

body.system-keyboard-open.system-text-input-active .card {
display: block;
padding: 8px;
}

body.system-keyboard-open.system-text-input-active .card > .portrait-current-panel,
body.system-keyboard-open.system-text-input-active .card .result-display,
body.system-keyboard-open.system-text-input-active #custom-keyboard {
display: none;
}

body.system-keyboard-open.system-text-input-active .input-group,
body.system-keyboard-open.system-text-input-active #expressionInput {
width: 100%;
}
}

@media (orientation: landscape) and (min-width: 560px) and (max-height: 520px) {
.card {
padding: 8px;
gap: 4px;
}

input[type="text"] {
padding: 8px 6px;
font-size: 1rem;
}

.result-display {
font-size: 1.05rem;
}

#custom-keyboard.visible {
grid-template-rows: repeat(5, clamp(32px, 9vh, 38px));
}

.key {
height: clamp(32px, 9vh, 38px);
}
}

@media (orientation: landscape) and (min-width: 560px) and (max-height: 430px) {
.history-pane {
gap: 8px;
}

#history-container {
height: auto;
}

.wide-current-panel {
display: block;
flex: 0 0 clamp(72px, 32%, 104px);
min-height: 0;
overflow: hidden;
border: 1px solid var(--border);
border-radius: 8px;
background-color: var(--input-bg);
clip-path: inset(0 round 8px);
contain: paint;
}

.card {
display: flex;
flex-direction: column;
}

.card > .portrait-current-panel {
display: none;
}

.card .input-group {
margin-top: auto;
flex: 0 0 auto;
}

.card .result-display,
#custom-keyboard.visible {
flex: 0 0 auto;
}
}

@media (horizontal-viewport-segments: 3), (orientation: landscape) and (min-width: 1100px) and (min-height: 560px) {
.container {
grid-template-columns: minmax(220px, 1.1fr) minmax(180px, 0.72fr) minmax(300px, 0.9fr);
gap: 10px;
}

.history-pane {
display: contents;
}

#history-container {
grid-column: 1;
grid-row: 1;
width: 100%;
height: 100%;
min-height: 0;
margin-bottom: 0;
border-radius: 8px;
clip-path: inset(0 round 8px);
}

.wide-current-panel {
grid-column: 2;
grid-row: 1;
display: block;
height: 100%;
min-height: 0;
overflow: hidden;
border: 1px solid var(--border);
border-radius: 8px;
background-color: var(--input-bg);
clip-path: inset(0 round 8px);
contain: paint;
}

#wide-current-numbers-list {
height: 100%;
max-height: none;
overflow-y: auto;
-webkit-overflow-scrolling: touch;
border-radius: 7px;
}

.card {
grid-column: 3;
grid-row: 1;
height: 100%;
display: flex;
flex-direction: column;
justify-content: flex-end;
align-items: stretch;
min-width: 0;
margin-top: 0;
}

.card > .portrait-current-panel {
display: none;
}

.card .input-group,
.card .result-display,
#custom-keyboard.visible {
flex: 0 0 auto;
}

body.system-keyboard-open.system-text-input-active .container {
grid-template-columns: minmax(0, 1fr) minmax(280px, 0.78fr);
}

body.system-keyboard-open.system-text-input-active .wide-current-panel {
display: none;
}

body.system-keyboard-open.system-text-input-active #history-container {
grid-column: 1;
height: 100%;
}

body.system-keyboard-open.system-text-input-active .card {
grid-column: 2;
display: block;
height: auto;
}
}

@media (orientation: landscape) and (min-width: 560px), (horizontal-viewport-segments: 2) {
body.left-hand-mode .history-pane {
grid-column: 2;
grid-row: 1;
gap: 8px;
}

body.left-hand-mode .wide-current-panel {
display: block;
flex: 0 0 clamp(72px, 32%, 104px);
min-height: 0;
overflow: hidden;
border: 1px solid var(--border);
border-radius: 8px;
background-color: var(--input-bg);
clip-path: inset(0 round 8px);
contain: paint;
}

body.left-hand-mode .card {
grid-column: 1;
grid-row: 1;
box-shadow: 5px 0 15px var(--shadow-card-color);
display: flex;
flex-direction: column;
justify-content: flex-end;
}

body.left-hand-mode .card > .portrait-current-panel {
display: none;
}

body.left-hand-mode .card .input-group,
body.left-hand-mode .card .result-display,
body.left-hand-mode #custom-keyboard.visible {
flex: 0 0 auto;
}

body.left-hand-mode.system-keyboard-open.system-text-input-active .history-pane {
grid-column: 2;
}

body.left-hand-mode.system-keyboard-open.system-text-input-active .card {
grid-column: 1;
}
}

@media (horizontal-viewport-segments: 3), (orientation: landscape) and (min-width: 1100px) and (min-height: 560px) {
body.left-hand-mode #history-container {
grid-column: 3;
grid-row: 1;
}

body.left-hand-mode .wide-current-panel {
grid-column: 2;
grid-row: 1;
display: block;
}

body.left-hand-mode .card {
grid-column: 1;
grid-row: 1;
box-shadow: 5px 0 15px var(--shadow-card-color);
}

body.left-hand-mode.system-keyboard-open.system-text-input-active .container {
grid-template-columns: minmax(280px, 0.78fr) minmax(0, 1fr);
}

body.left-hand-mode.system-keyboard-open.system-text-input-active #history-container {
grid-column: 2;
}

body.left-hand-mode.system-keyboard-open.system-text-input-active .card {
grid-column: 1;
}
}

/* The current-expression list grows by content and is rendered on one side only. */
.portrait-current-panel {
height: var(--current-list-height);
flex: 0 1 var(--current-list-height);
min-height: 0;
max-height: 100%;
}

.wide-current-panel {
height: min(var(--current-list-height), 100%);
flex: 0 0 min(var(--current-list-height), 100%);
min-height: 0;
max-height: 100%;
overflow: hidden;
border: 1px solid var(--border);
border-radius: 8px;
background-color: var(--input-bg);
clip-path: inset(0 round 8px);
contain: paint;
}

#current-numbers-list,
#wide-current-numbers-list {
height: 100%;
max-height: none;
min-height: 0;
overflow-y: auto;
-webkit-overflow-scrolling: touch;
touch-action: pan-y;
overscroll-behavior-y: contain;
scrollbar-gutter: auto;
}

#history-container,
#current-numbers-list,
#wide-current-numbers-list {
scrollbar-width: auto;
scrollbar-color: var(--scrollbar-thumb) var(--scrollbar-track);
}

#history-container::-webkit-scrollbar,
#current-numbers-list::-webkit-scrollbar,
#wide-current-numbers-list::-webkit-scrollbar {
width: var(--scrollbar-width);
background: var(--surface-sunken);
}

#history-container::-webkit-scrollbar-track,
#current-numbers-list::-webkit-scrollbar-track,
#wide-current-numbers-list::-webkit-scrollbar-track {
background: var(--scrollbar-track);
border-radius: 6px;
margin-block: 4px;
}

#history-container::-webkit-scrollbar-thumb,
#current-numbers-list::-webkit-scrollbar-thumb,
#wide-current-numbers-list::-webkit-scrollbar-thumb {
min-height: 28px;
background-color: var(--scrollbar-thumb);
border: 1px solid var(--surface-sunken);
border-radius: 6px;
}

body:not(.has-current-entries) .portrait-current-panel,
body:not(.has-current-entries) .wide-current-panel,
body.has-current-entries:not(.current-list-in-history) .wide-current-panel,
body.has-current-entries.current-list-in-history .portrait-current-panel {
display: none !important;
}

body.has-current-entries:not(.current-list-in-history) .portrait-current-panel,
body.has-current-entries.current-list-in-history .wide-current-panel {
display: block;
height: min(var(--current-list-height), 100%);
flex: 0 0 min(var(--current-list-height), 100%);
min-height: 0;
max-height: 100%;
}

body.has-current-entries:not(.current-list-in-history) .portrait-current-panel {
height: var(--current-list-height);
flex: 0 1 var(--current-list-height);
}

body.has-current-entries.current-list-in-history .history-pane {
gap: 8px;
}

body.has-current-entries.current-list-in-history.current-list-fills-history .history-pane {
gap: 0;
}

body.has-current-entries.current-list-in-history.current-list-fills-history #history-container {
display: none !important;
}

body.has-current-entries.current-list-in-history.current-list-fills-history .wide-current-panel {
height: 100%;
flex-basis: 100%;
}

.card {
justify-content: flex-end;
}

.card .input-group,
.card .result-display,
#custom-keyboard.visible {
flex: 0 0 auto;
}

@media (orientation: portrait) and (max-width: 699px), (max-width: 559px) {
.card {
max-height: calc(100% - 20px);
}
}

@media (orientation: landscape) and (min-width: 560px), (min-width: 700px) {
.card {
display: flex;
flex-direction: column;
justify-content: flex-end;
}

.card .input-group {
margin-top: auto;
}

.card .input-group,
.card .result-display,
#custom-keyboard.visible {
flex: 0 0 auto;
}

body.has-current-entries:not(.current-list-in-history) .card > .portrait-current-panel {
display: block;
height: var(--current-list-height);
flex: 0 1 var(--current-list-height);
}
}

@media (horizontal-viewport-segments: 3), (orientation: landscape) and (min-width: 1100px) and (min-height: 560px) {
.history-pane {
grid-column: 1 / 3;
grid-row: 1;
display: flex;
flex-direction: column;
min-width: 0;
min-height: 0;
gap: 8px;
}

#history-container,
.wide-current-panel {
grid-column: auto;
grid-row: auto;
width: 100%;
}

.card {
grid-column: 3;
grid-row: 1;
}

body.left-hand-mode .history-pane {
grid-column: 2 / 4;
grid-row: 1;
}

body.left-hand-mode .card {
grid-column: 1;
grid-row: 1;
}

body.system-keyboard-open.system-text-input-active .history-pane {
grid-column: 1;
}

body.system-keyboard-open.system-text-input-active .card {
grid-column: 2;
}

body.left-hand-mode.system-keyboard-open.system-text-input-active .history-pane {
grid-column: 2;
}

body.left-hand-mode.system-keyboard-open.system-text-input-active .card {
grid-column: 1;
}
}

/* History grows one entry at a time and only scrolls after it reaches its limit. */
body:not(.has-history-entries) #history-container {
display: none !important;
}

body.has-history-entries #history-container {
display: flex;
height: min(var(--history-list-height), 100%);
flex: 0 1 var(--history-list-height);
min-height: 0;
max-height: 100%;
}

#editModal {
display: none;
position: fixed;
inset: 0;
background: var(--overlay-scrim);
justify-content: center;
align-items: center;
z-index: 9999;
}

#editModalContent {
background: var(--card-bg);
padding: 10px;
border-radius: 8px;
width: 90%;
max-width: 300px;
box-sizing: border-box;
}

#editModalContent h3 { margin: 0 0 4px 0; color: var(--primary); }

#editInput {
width: 100%;
padding: 6px;
font-size: 0.9rem;
border-radius: 6px;
border: 1px solid var(--border);
background-color: var(--input-bg);
color: var(--text);
box-sizing: border-box;
}

#editButtons { margin-top: 8px; text-align: right; }

#editCancelBtn, #editConfirmBtn {
padding: 4px 8px;
border-radius: 5px;
border: none;
cursor: pointer;
user-select: none;
}

#editCancelBtn { margin-right: 4px; background-color: var(--control-neutral); color: var(--text-strong); }
#editConfirmBtn { background-color: var(--primary); color: var(--primary-contrast); }

#settingsModal {
display: none;
position: fixed;
inset: 0;
background: var(--overlay-scrim);
justify-content: center;
align-items: center;
z-index: 10001;
}

#settingsContent {
background: var(--card-bg);
padding: 15px;
border-radius: 8px;
width: 90%;
max-width: 320px;
box-sizing: border-box;
}

#settingsContent h3 { margin: 0 0 10px 0; color: var(--primary); }
.setting-item { margin-bottom: 10px; }
.setting-item label { display: block; margin-bottom: 5px; }
#uiScaleSlider { width: 100%; }
#closeSettingsBtn { width: 100%; padding: 8px; background-color: var(--primary); color: var(--primary-contrast); border: none; border-radius: 5px; cursor: pointer; }

.settings-legal-links {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 8px;
margin: 12px 0 8px;
}

.settings-legal-links button {
min-width: 0;
padding: 8px 6px;
border: 1px solid var(--border);
background: var(--input-bg);
color: var(--text);
font-size: 0.82rem;
}

#openSourceLicensesBtn { grid-column: 1 / -1; }

#legalConsentModal,
#legalViewerModal {
display: none;
position: fixed;
inset: 0;
padding:
  max(env(safe-area-inset-top, 0px), 8px)
  max(env(safe-area-inset-right, 0px), 8px)
  max(env(safe-area-inset-bottom, 0px), 8px)
  max(env(safe-area-inset-left, 0px), 8px);
background: var(--overlay-scrim-max);
align-items: center;
justify-content: center;
z-index: 40000;
}

#legalConsentPanel,
#legalViewerPanel {
width: min(100%, 820px);
height: min(100%, 920px);
display: flex;
flex-direction: column;
overflow: hidden;
border: 1px solid var(--border);
border-radius: 8px;
background: var(--card-bg);
box-shadow: var(--shadow-modal);
}

.legal-toolbar {
flex: 0 0 auto;
display: flex;
align-items: center;
gap: 10px;
padding: 12px;
border-bottom: 1px solid var(--border);
background: var(--card-bg);
}

.legal-heading {
flex: 1;
min-width: 0;
}

.legal-heading h2 {
margin: 0;
color: var(--primary);
font-size: 1.2rem;
line-height: 1.35;
}

.legal-heading p {
margin: 4px 0 0;
color: var(--timestamp);
font-size: 0.78rem;
line-height: 1.45;
}

.legal-language-select {
width: min(42%, 190px);
height: 40px;
padding: 0 8px;
border: 1px solid var(--border);
border-radius: 6px;
background: var(--input-bg);
color: var(--text);
font-size: 0.86rem;
}

#legalConsentContent,
#legalViewerContent {
flex: 1 1 auto;
min-height: 0;
overflow-y: auto;
-webkit-overflow-scrolling: touch;
padding: 18px;
user-select: text;
overscroll-behavior: contain;
}

.legal-viewer-tabs {
display: grid;
grid-template-columns: repeat(3, minmax(0, 1fr));
gap: 1px;
flex: 0 0 auto;
background: var(--border);
border-bottom: 1px solid var(--border);
}

.legal-viewer-tab {
min-width: 0;
min-height: 42px;
padding: 7px 5px;
border: 0;
border-radius: 0;
background: var(--input-bg);
color: var(--text);
font-size: 0.78rem;
line-height: 1.25;
overflow-wrap: anywhere;
}

.legal-viewer-tab.active {
background: var(--primary);
color: var(--primary-contrast);
}

#legalViewerContent.oss-viewer-host {
padding: 0;
overflow: hidden;
}

.oss-license-frame {
display: block;
width: 100%;
height: 100%;
border: 0;
background: var(--card-bg);
}

#legalConsentContent:focus,
#legalViewerContent:focus {
outline: 2px solid var(--primary);
outline-offset: -2px;
}

.legal-read-note {
margin: 0 0 20px;
padding: 13px 15px;
border-left: 4px solid var(--primary);
background: var(--input-bg);
color: var(--text);
font-size: 0.9rem;
line-height: 1.6;
}

[dir="rtl"] .legal-read-note {
border-left: 0;
border-right: 4px solid var(--primary);
}

.legal-document + .legal-document {
margin-top: 30px;
padding-top: 28px;
border-top: 2px solid var(--border);
}

.legal-document h2 {
margin: 0;
color: var(--primary);
font-size: 1.35rem;
line-height: 1.35;
}

.legal-document > p {
margin: 8px 0 18px;
color: var(--timestamp);
font-size: 0.9rem;
line-height: 1.65;
}

.legal-document section {
padding: 14px 0;
border-top: 1px solid var(--divider-soft);
}

.legal-document section h3 {
margin: 0 0 6px;
font-size: 0.98rem;
line-height: 1.45;
}

.legal-document section p {
margin: 0;
color: var(--text-secondary);
font-size: 0.87rem;
line-height: 1.7;
}

#legalBottomMarker {
margin-top: 24px;
padding: 18px;
border: 1px solid var(--border);
border-radius: 6px;
background: var(--input-bg);
text-align: center;
}

#legalBottomMarker strong,
#legalBottomMarker p {
display: block;
margin: 0;
}

#legalBottomMarker p {
margin-top: 5px;
color: var(--timestamp);
font-size: 0.82rem;
}

.legal-actions {
flex: 0 0 auto;
display: grid;
grid-template-columns: 1fr 1.35fr;
gap: 8px;
padding: 10px 12px 12px;
border-top: 1px solid var(--border);
background: var(--card-bg);
}

#legalStatus {
grid-column: 1 / -1;
min-height: 20px;
color: var(--timestamp);
font-size: 0.78rem;
line-height: 1.4;
text-align: center;
}

#declineLegalBtn,
#agreeLegalBtn,
#closeLegalViewerBtn {
min-height: 42px;
color: var(--text-strong);
}

#declineLegalBtn { background: var(--control-neutral-strong); }
/* Dark text on the accent: white would only reach 2.63:1 on the brighter blue. */
#agreeLegalBtn,
#closeLegalViewerBtn { background: var(--primary); color: var(--primary-contrast); }
/* Was #a7a7a7 on #4b4b4b (3.63:1) on the button users stare at during the countdown. */
#agreeLegalBtn:disabled { background: var(--control-disabled-bg); color: var(--text-disabled); cursor: default; }

#closeLegalViewerBtn {
height: 40px;
min-height: 40px;
padding: 0 12px;
white-space: nowrap;
}

@media (max-width: 520px) {
.legal-toolbar { align-items: stretch; flex-direction: column; padding: 10px; }
.legal-language-select { width: 100%; }
#legalConsentContent, #legalViewerContent { padding: 14px; }
.legal-actions { grid-template-columns: 1fr; }
#legalStatus { grid-column: 1; }
}

#disclaimerModal {
display: none;
position: fixed;
inset: 0;
padding:
  max(env(safe-area-inset-top, 0px), 12px)
  max(env(safe-area-inset-right, 0px), 12px)
  max(env(safe-area-inset-bottom, 0px), 12px)
  max(env(safe-area-inset-left, 0px), 12px);
background: var(--overlay-scrim-strong);
align-items: center;
justify-content: center;
z-index: 31000;
}

#disclaimerPanel {
width: min(100%, 460px);
padding: 20px;
border: 1px solid var(--border);
border-radius: 8px;
background: var(--card-bg);
box-shadow: var(--shadow-modal);
}

#disclaimerTitle {
margin: 0;
color: var(--primary);
font-size: 1.3rem;
line-height: 1.35;
}

#disclaimerText {
margin: 14px 0 18px;
color: var(--text);
font-size: 0.94rem;
line-height: 1.75;
user-select: text;
}

#acceptDisclaimerBtn {
width: 100%;
min-height: 42px;
background: var(--primary);
color: var(--primary-contrast);
font-size: 0.95rem;
}

#usageGuideModal {
display: none;
position: fixed;
inset: 0;
padding:
  max(env(safe-area-inset-top, 0px), 12px)
  max(env(safe-area-inset-right, 0px), 12px)
  max(env(safe-area-inset-bottom, 0px), 12px)
  max(env(safe-area-inset-left, 0px), 12px);
background: var(--overlay-scrim-strong);
align-items: center;
justify-content: center;
z-index: 30000;
}

#usageGuidePanel {
width: min(100%, 720px);
max-height: 100%;
display: flex;
flex-direction: column;
overflow: hidden;
border: 1px solid var(--border);
border-radius: 8px;
background: var(--card-bg);
box-shadow: var(--shadow-modal);
}

.usage-guide-toolbar {
flex: 0 0 auto;
display: flex;
align-items: end;
gap: 8px;
padding: 12px;
border-bottom: 1px solid var(--border);
background: var(--card-bg);
}

.usage-guide-language {
flex: 1;
min-width: 0;
}

.usage-guide-language label {
display: block;
margin-bottom: 5px;
color: var(--timestamp);
font-size: 0.76rem;
}

#usageGuideLanguageSelect {
width: 100%;
height: 38px;
padding: 0 8px;
border: 1px solid var(--border);
border-radius: 6px;
background: var(--input-bg);
color: var(--text);
font-size: 0.9rem;
}

#closeUsageGuideBtn {
height: 38px;
padding: 0 12px;
background: var(--primary);
color: var(--primary-contrast);
white-space: nowrap;
}

#usageGuideContent {
min-height: 0;
overflow-y: auto;
-webkit-overflow-scrolling: touch;
padding: 16px;
user-select: text;
}

#usageGuideTitle {
margin: 0;
color: var(--primary);
font-size: 1.35rem;
line-height: 1.3;
}

#usageGuideIntro {
margin: 8px 0 16px;
color: var(--timestamp);
font-size: 0.9rem;
line-height: 1.55;
}

.usage-guide-section {
margin-top: 18px;
}

.usage-guide-section:first-child {
margin-top: 0;
}

.usage-guide-section h3 {
margin: 0;
padding: 0 0 8px;
border-bottom: 1px solid var(--border);
color: var(--text);
font-size: 1rem;
line-height: 1.4;
}

.usage-guide-item {
padding: 11px 0;
border-bottom: 1px solid var(--divider-faint);
}

.usage-guide-item:last-child {
border-bottom: none;
}

.usage-guide-item strong {
display: block;
margin-bottom: 4px;
color: var(--text-strong);
font-size: 0.92rem;
line-height: 1.45;
}

.usage-guide-item p {
margin: 0;
color: var(--text-secondary);
font-size: 0.86rem;
line-height: 1.6;
white-space: pre-line;
}

@media (max-width: 480px) {
#usageGuideModal {
padding:
  max(env(safe-area-inset-top, 0px), 6px)
  max(env(safe-area-inset-right, 0px), 6px)
  max(env(safe-area-inset-bottom, 0px), 6px)
  max(env(safe-area-inset-left, 0px), 6px);
}

.usage-guide-toolbar {
padding: 9px;
}

#usageGuideContent {
padding: 13px;
}

#closeUsageGuideBtn {
padding-inline: 10px;
}
}

/* Sat dead centre, covering the result readout and the list the user is reading.
   Moved above the card and given a small rise so it reads as a transient message. */
#toast {
  position: fixed;
  top: max(calc(env(safe-area-inset-top, 0px) + 56px), 56px);
  left: 50%;
  transform: translate(-50%, -6px);
  max-width: min(88vw, 420px);
  text-align: center;
  background-color: var(--toast-bg);
  color: var(--text-strong);
  padding: 10px 20px;
  border: 1px solid var(--border);
  border-radius: 20px;
  font-size: 0.9rem;
  line-height: 1.45;
  box-shadow: var(--shadow-modal);
  z-index: 20000;
  opacity: 0;
  transition: opacity var(--motion-normal) ease, transform var(--motion-normal) ease;
  pointer-events: none;
}
#toast.show {
  opacity: 1;
  transform: translate(-50%, 0);
}

/* Modals were toggled straight from display:none to flex with no transition.
   The animation runs when the element becomes displayed, so no JS change is needed. */
#remarkModal,
#searchModal,
#editModal,
#settingsModal,
#legalConsentModal,
#legalViewerModal,
#disclaimerModal,
#usageGuideModal {
  animation: modal-fade-in var(--motion-fast) ease-out;
}

@keyframes modal-fade-in {
  from { opacity: 0; }
  to { opacity: 1; }
}

#remarkModalContent,
#searchModalContent,
#editModalContent,
#settingsContent,
#legalConsentPanel,
#legalViewerPanel,
#disclaimerPanel,
#usageGuidePanel {
  animation: modal-panel-in var(--motion-fast) ease-out;
}

@keyframes modal-panel-in {
  from { opacity: 0; transform: translateY(8px) scale(0.985); }
  to { opacity: 1; transform: none; }
}

/* --- OLED burn-in protection (see initBurnInProtection in the script) --- */
/* The shift moves <body> by 1px, so the page background must match underneath. */
html { background: var(--bg-color); }
body { transition: filter 3s ease; }
/* Barely-perceptible dim while idle; static UI elements age the panel slower. */
body.screen-rest { filter: brightness(0.94); }

/* Respect the system "reduce motion" setting: keep state changes instant but visible.
   Long-press still works because the JS timers are independent of these animations. */
@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
    scroll-behavior: auto !important;
  }

  .key:active,
  .key.key-active,
  .legal-info-button:active,
  button:active {
    transform: none;
  }

  /* The long-press progress bar must NOT be collapsed to ~0ms, or the key would look
     fully charged the instant it is touched and promise an action that has not fired.
     Drop the fill entirely and rely on the static hold colour instead. */
  .key.key-hold-ready {
    animation: none !important;
    background-image: none;
    background-size: 0 100%;
  }
}
